*** empty log message ***
authorLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 4 Mar 1997 01:36:21 +0000 (01:36 +0000)
committerLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 4 Mar 1997 01:36:21 +0000 (01:36 +0000)
23 files changed:
lisp/ChangeLog
lisp/Makefile
lisp/dgnushack.el
lisp/doc.txt
lisp/gnus-mh.el
lisp/gnus-uu.el
lisp/gnus-visual.el
lisp/gnus.el
lisp/nnbabyl.el
lisp/nndigest.el
lisp/nndir.el
lisp/nndoc.el
lisp/nnfolder.el [new file with mode: 0644]
lisp/nnheader.el
lisp/nnkiboze.el
lisp/nnmail.el
lisp/nnmbox.el
lisp/nnmh.el
lisp/nnml.el
lisp/nnspool.el
lisp/nntp.el
lisp/nnvirtual.el
texi/gnus.texi

index d9aabdd..ed798d2 100644 (file)
@@ -1,3 +1,510 @@
+Thu Mar 23 06:29:03 1995  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: 0.39 is released.
+
+Thu Mar 23 04:10:52 1995  Lars Magne Ingebrigtsen  <larsi@mimir.ifi.uio.no>
+
+       * gnus.el (gnus-mail-other-window-using-mail): Allow yanking, and
+       fix winconf on exit.
+       (gnus-group-faq-directory): Wrong default value.
+       (gnus-group-fetch-faq): Did not work.
+       (gnus-score-save): Would save score files even when there wasn't
+       one. 
+
+       * gnus-uu.el (gnus-uu-decode-uu-and-save): Use an uu default
+       directory. 
+
+       * nnfolder.el (nnfolder-read-folder): Would bug out if there was
+       no active file.
+
+       * gnus.el (gnus-ask-server-for-new-groups): Did not really work
+       for any backends.
+       (gnus-group-unsubscribe-group): Would not let you susbcribe to
+       killed groups.
+       (gnus-summary-catchup): Would not catchup expired articles. 
+
+Thu Mar 22 14:23:03 1995  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: 0.38 is released.
+
+Wed Mar 22 13:55:21 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * nntp.el (nntp-send-mode-reader): Blocked reading of active list.
+
+Wed Mar 22 13:55:05 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el: 0.37 is released. 
+
+Wed Mar 22 08:37:15 1995  Lars Magne Ingebrigtsen  <larsi@surt.ifi.uio.no>
+
+       * nntp.el (nntp-send-mode-reader): Actually send the mode reader
+       command. 
+
+Wed Mar 22 00:00:01 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-make-threads-and-expunge): Really, really expunge
+       low-scored articles. Right.
+       (gnus-make-threads): Simpler function to speed things up when
+       expunging is not needed.
+
+       * nnvirtual.el (nnvirtual-create-mapping): Would bug out in the
+       presence of bogus groups.
+
+       * nnspool.el (nnspool-possibly-change-directory): Don't error out
+       when errors occur, but return a message instead.
+
+       * nndoc.el (nndoc-possibly-change-buffer): Would bug out if the
+       file didn't exist.
+
+       * gnus.el (gnus-mark-xrefs-as-read): Handled crossrefs to groups
+       with no read articles strangely. Also didn't perform crossreffing
+       when select methods were only almost equal.
+       (gnus-make-articles-unread): Would bug out when nnmh was the
+       native server. 
+
+       * nnbabyl.el (nnbabyl-read-mbox): Did not properly label articles. 
+
+       * gnus.el (gnus-set-mode-line): Do unread-and-unticked by default. 
+       (gnus-summary-pop-article): New command and keystroke.
+       (gnus-mode-non-string-length): New variable.
+       (gnus-set-mode-line): Use it.
+       (gnus-score-mode): New mode to edit score files. 
+       (gnus-inews-date): Did the opposite thing of what it was supposed
+       to do with time zones.
+       (gnus-group-make-group): Don't prompt for address if that is
+       irrelevant. 
+
+Tue Mar 21 10:01:20 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * nnfolder.el (nnfolder-read-folder): Would only work if incoming
+       mail was split by Gnus.
+
+       * gnus.el (gnus-score-transform-old-to-new): Function for
+       rewriting old score files.
+       (gnus-score-expiry-days): Name change from
+       `gnus-kill-expiry-days'. 
+       (gnus-score-headers): All score functions rewritten to deal with
+       the new format.
+       (gnus-summary-goto-unread): New variable.
+       (gnus-summary-mark-forward): Use it.
+
+Tue Mar 21 04:50:05 1995  Lars Magne Ingebrigtsen  <larsi@gymir.ifi.uio.no>
+
+       * gnus.el (gnus-summary-mark-article): Low-scored articles in
+       auto-expirable grups should be expirable.
+
+Mon Mar 20 00:07:36 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-post-news): Also prompt for Subject, if that is
+       required. 
+       (gnus-global-score-files): New variable.
+       (gnus-score-score-files): Use it.
+       (gnus-score-save): Don't attempt to save read-only score files. 
+       (gnus-summary-mode-map): Score map error.
+       (gnus-score-load-score-alist): New function.
+       (gnus-summary-*-raise/lower-by-id): New commands and keystrokes
+       for raising/lowering by message-id. 
+
+       * nntp.el (nntp-request-post-buffer): Don't rely on any Gnus
+       variables. 
+
+       * gnus.el: Lots and lots of doc fixes.
+       (gnus-execute): Would not allow use from summary buffer.
+       (gnus-local-timezone): Removed variable.
+       (gnus-summary-followup): Don't display article.
+
+Sun Mar 19 04:34:30 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-activate-newsgroup): If a server can't be reached,
+       there's not much point in trying to request groups from it.
+       (gnus-mark-xrefs-as-read): Also do Xrefs to unsubscribed groups
+       unconditionally if virtual groups are used.
+
+       * nntp.el (nntp-open-server): Set up timeouts for connections. 
+       (nntp-connection-timeout): New variable.
+
+       * gnus.el (gnus-get-unread-articles): Allow activation of virtual
+       groups. 
+       (gnus-kill-file-mode): Reinstated most GNUS functions and took out
+       all gnus-raise/lower code.
+       (gnus-summary-mode): Doc fix. (Snicker.)
+       (gnus): Move startup hook backwards.
+       (gnus-articles-to-read): Use total-number as the default. 
+       (gnus-member-of-range): Minor inaccuracy.
+       (gnus-sorted-complement): New, faster function.
+       (gnus-articles-to-read): Use it.
+       (gnus-sorted-intersection, gnus-set-sorted-intersection): New
+       functions. 
+       (gnus-select-newsgroup): Use them.
+
+Sun Mar 19 02:46:15 1995  Lars Magne Ingebrigtsen  <larsi@surt.ifi.uio.no>
+
+       * nnvirtual.el (nnvirtual-retrieve-headers): Would leave extra
+       spaces before the Xref sometimes, causing problems for subsequent
+       Xref handling.
+
+Sun Mar 19 02:46:01 1995  Lars Magne Ingebrigtsen  <larsi@surt.ifi.uio.no>
+
+       * gnus.el: 0.36 is released.
+
+Sun Mar 19 00:03:37 1995  Lars Magne Ingebrigtsen  <larsi@surt.ifi.uio.no>
+
+       * nnvirtual.el (nnvirtual-retrieve-headers): When NOV lines only
+       had seven tabs, this would deliver incorrect results.
+
+       * gnus.el (gnus-execute-1): Would not search through article
+       bodies. 
+       (gnus-summary-prepare-threads): 'empty was not properly respected. 
+
+       * nntp.el (nntp-open-server): Would bug out if server refused
+       connection. 
+
+       * gnus.el (gnus-make-threads): Expunge non-scored articles, if
+       wanted. 
+       (gnus-summary-prepare-threads): When not threading, expunge
+       nmon-scored, if wanted. 
+
+Sat Mar 18 23:39:47 1995  Lars Magne Ingebrigtsen  <larsi@surt.ifi.uio.no>
+
+       * gnus.el (gnus-summary-insert-line): Would bug out if
+       gnus-summary-default-score was nil.
+       (gnus-inews-news): If `gnus-mail-courtesy-message' is nil, don't
+       append one. 
+
+Sat Mar 18 16:39:59 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-group-edit-group): Use pp.
+       (gnus-score-change-score-file): New command and keystroke. 
+
+       * nntp.el (nntp-request-post-buffer): Pass the request on to
+       nnmail if that is wanted.
+
+       * gnus.el (gnus-post-news): Send mail even when requesting post
+       when `to-address' is set.
+
+       * nntp.el (nntp-server-opened-hook): Doc fix.
+       (nntp-send-mode-reader, nntp-send-authinfo): New functions. 
+
+       * gnus.el (gnus-score-find-bnews): Would bug out when presented
+       with the file "SCORE". 
+
+Fri Mar 17 14:05:54 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-summary-exit): Buffer-local vectors would not be
+       garbage-collected, leading to a major memory drain.
+
+Thu Mar 16 22:14:14 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-update-read-articles): Would mark ticked articles
+       not displayed as read.
+       (gnus-member-of-range): Also accept single-range ranges.
+       (gnus-get-unread-articles-in-group): Adjust ticked and dormant
+       articles before computing the number of unread articles. 
+       (gnus-summary-next-article): Would need an extra C-n before
+       moving to the right groups (sort of).
+
+Thu Mar 16 16:52:19 1995  Lars Magne Ingebrigtsen  <larsi@beli.ifi.uio.no>
+
+       * gnus.el: 0.35 is released.
+
+Thu Mar 16 15:47:33 1995  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el (gnus-read-descriptions-file): Changed pattern to
+       delete. 
+       (gnus-group-describe-group): Added "force" prefix.
+
+Thu Mar 16 00:08:23 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * nnvirtual.el (nnvirtual-create-mapping): Be more lenient with
+       component groups that can't be requested.
+
+       * nnml.el (nnml-possibly-change-directory): Don't signal errors.
+
+       * gnus.el (gnus-group-get-new-news-this-group): Display better
+       error messages when errors occur.
+
+       * nnspool.el (nnspool-request-group): Return an error message if
+       the group can't be selected.
+
+       * nntp.el (nntp-open-server): Don't bug out if getting a C-g while
+       waiting for initial contact.
+
+       * nnspool.el (nnspool-request-newgroups): Now also supported by
+       nnspool. 
+
+       * gnus-visual.el (gnus-group-make-menu-bar): -make-doc-group did
+       not exist.
+
+       * gnus.el (gnus-group-faq-directory): Missing leading slash. 
+
+       * nnfolder.el (nnfolder-request-list): The first time this is
+       called, create the active file.
+
+       * gnus.el (gnus-group-change-level): When subscribing to killed
+       groups with no articles, would enter wrong number of read
+       articles. 
+
+       * nnspool.el (nnspool-server-opened): Would return t even when not
+       opened. 
+
+Wed Mar 15 23:47:52 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-get-new-news-in-group): Give a sensible return
+       value. 
+       (gnus-group-get-new-news-this-group): Beep if group can't be
+       activated. 
+
+       * nnfolder.el (nnfolder-request-group): Complain if the group
+       doesn't exist.
+
+Wed Mar 15 19:14:47 1995  Lars Magne Ingebrigtsen  <larsi@beli.ifi.uio.no>
+
+       * gnus.el (gnus-summary-refer-article): Would behave strangely
+       when refering an article already present in the summary buffer.
+
+Wed Mar 15 17:53:14 1995  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: 0.34 is released.
+
+Wed Mar 15 00:53:47 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-post-news): Would bug out when posting from the
+       group buffer.
+
+       * gnus-uu.el (gnus-uu-grab-articles): Don't mark ticked (etc)
+       articles as read.
+
+       * gnus.el (gnus-find-method-for-group): Before no groups were
+       entered, a bug here would result in an incorrect error message
+       when the nntp server couldn't be contacted.
+       (gnus-summary-mode-map): Several changes.
+       (gnus-read-descriptions-file): Would delete lines that were valid. 
+
+Tue Mar 14 23:11:30 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-summary-next-article): Enable the use of C-n and
+       C-p when choosing "next group" in the summary buffer.
+       (gnus-summary-recenter): Behaves in a slightly modified
+       fashion. Now also works with absolutely all sizes.
+
+Mon Mar 13 11:13:41 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-summary-catchup): Would mark all as read, even if
+       to-here was non-nil.
+       (gnus-summary-catchup-to-here): Disable prompting.
+       (gnus-summary-update-lines): Do updateing even with gnus-visual
+       nil. 
+       (gnus-score-load-file): New atom - mark-and-expunge.
+
+       * nnmail.el (nnmail-split-methods): New semantics.
+       (nnmail-article-group): Use them.
+
+       * gnus.el (gnus-group-list-matching): Fix and bound to keys and
+       menus.
+       (gnus-group-list-all-matching): New command.
+       (gnus-group-sort-groups): Would make all groups disappear. 
+
+       * (-request-move-article, -request-accept-article): Only do saving
+       after the last article has been moved.
+
+       * nnml.el (nnml-save-nov): Only save modified buffers.
+
+       * gnus.el (gnus-summary-move-article): Only save nov files once
+       when moving many articles.
+       (gnus-post-news): Did not allow interactive calls. 
+
+Sun Mar 12 16:52:50 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-mail-forward-using-mail): Would not bind
+       `gnus-mail-send-and-exit' to `C-c C-c'.
+
+Sun Mar 12 16:30:28 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el: 0.33 is released.
+
+Sun Mar 12 09:42:11 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-summary-prepare-threads, gnus-make-threads):
+       Really expunge all low-marked articles if that is wanted.
+       (gnus-score-score-files): Would bug out if `gnus-use-long-names'
+       was nil and no score file exists.
+
+Sat Mar 11 19:14:05 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-summary-toggle-threads): Go to the last article if
+       none is present on the current line.
+       (gnus-summary-prepare-threads): Cull dormant and low-scored
+       articles when displaying non-threaded summary buffers.
+       (gnus-post-news, gnus-mail-reply-using-mail): Respect
+       `gnus-use-full-window'. 
+       (gnus-summary-copy-article): New command and keystroke.
+
+Fri Mar 10 05:24:11 1995  Lars Ingebrigtsen  <lmi@eyesore.no>
+
+       * gnus.el: 0.32 is released.
+
+Fri Mar 10 05:24:11 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-summary-next-article, gnus-summary-prev-article,
+       gnus-summary-prev-group):  New implementations.
+       (gnus-article-prepare): The summary mode line would say "1 unread"
+       when there were none.
+       (gnus-summary-toggle-header): Did not hide headers after using
+       MIME. 
+       (gnus-check-bogus-newsgroups): Removed checking for duplicate
+       killed groups. 
+       (gnus-check-duplicate-killed-groups): New function.
+       (gnus-summary-update-mark): Allow summary-clear-mark to clear even
+       the low-score-mark.
+       (gnus-check-first-time-used): Don't re-subscribe default groups
+       when re-scanning, before creating the .newsrc files.
+
+       * gnus-uu.el (gnus-uu-decode-save): Insisted on saving to an
+       existing file. 
+
+Thu Mar  9 08:44:18 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * nnfolder.el (nnfolder-request-move-article): Did not work.
+
+       * nnmbox.el (nnmbox-request-move-article): Did not work at all. 
+
+       * nnvirtual.el (nnvirtual-retrieve-headers): Did not properly
+       translate xrefs from foreign groups.
+
+Mon Mar  6 06:13:26 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-summary-fetch-faq): New command and keystroke. 
+       (gnus-group-faq-directory): New variable.
+       (gnus-group-fetch-faq): New command and keystroke.
+       (gnus-apply-kill-file): No longer calls expunge-below.
+
+       * nntp.el (nntp-request-group-description): New function.
+
+       * gnus.el (gnus-extract-address-components): Understands some
+       formats better.
+       (gnus-cut-thread): Make sure all expunged articles are marked as
+       read. 
+       (gnus-group-sort-groups): New command and keystroke.
+       (group-group-sort-by-alphabet, gnus-group-sort-by-unread,
+       gnus-group-sort-by-level): New functions.
+       (gnus-group-sort-function): New variable.
+       (gnus-group-describe-group): Use XGTITLE for group descriptions.
+       (gnus-group-get-description): New function.
+       (gnus-request-group-description): New function.
+
+       * nnmbox.el (nnmbox-request-move-article): Did not work and would
+       destroy the active list.
+
+       * gnus.el (gnus-score-load-file): Add a 'touched to the alist if
+       there isn't one already.
+       (gnus-score-save): Remove 'touched before writing score file. 
+       (gnus-score-find-bnews): Always return the local score file, even
+       if it doesn't exist.
+       (gnus-score-load-file): Really execute special atoms.
+       (gnus-score-set, gnus-score-get): Return to the old definitions of
+       these functions.
+       (gnus-cut-thread): Cut dormant and ancient articles from the
+       threads. 
+       (gnus-summary-show-all-dormant): New implementation.
+       (gnus-summary-hide-all-dormant): New command and keystroke.
+       (gnus-make-threads): Now expunges articles with low scores. 
+       (gnus-summary-show-all-expunged): New implementation.
+       (gnus-summary-catchup): Did not mark expunged articles as read. 
+
+Sun Mar  5 01:29:49 1995  Lars Magne Ingebrigtsen  <larsi@hymir.ifi.uio.no>
+
+       * gnus.el (gnus-summary-mark-article): Also auto-expire caught up
+       articles. 
+       (gnus-group-make-kiboze-group): Would produce incorrect score
+       files. 
+       (gnus-group-insert-group-line): Would scroll the top off the
+       screen. 
+
+Sat Mar  4 02:32:11 1995  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el (gnus-summary-read-group): Would do strange stuff to the
+       window configuration when not using full screen.
+       (gnus-get-unread-articles-in-group): Check for illegal read
+       numbers. 
+
+       * gnus-uu.el (gnus-uu-save-files): Would bug if the file already
+       existed.
+
+Sat Mar  4 00:32:07 1995  Lars Magne Ingebrigtsen  <larsi@hymir.ifi.uio.no>
+
+       * gnus.el (gnus-mark-xrefs-as-read): Would compute the wrong
+       number of unread articles.
+
+Fri Mar  3 23:52:28 1995  Lars Magne Ingebrigtsen  <larsi@hymir.ifi.uio.no>
+
+       * gnus.el (gnus-group-search-forward): Would ignore level 5
+       groups. 
+
+Fri Mar  3 00:41:42 1995  Lars Magne Ingebrigtsen  <larsi@surt.ifi.uio.no>
+
+       * nnml.el (nnml-request-group): Would not work if the active file
+       was changed from without.
+
+       * gnus.el (gnus-summary-move-article): Have the group prefix be
+       the initial string.
+       (gnus-group-edit-group-done): pop instead of switch to edit
+       buffer. 
+       (gnus-group-set-info): Now also accepts group name changes.
+       (gnus-group-prepare-flat): Sort killed and zombie groups.
+       (gnus-extract-address-components): New variable.
+       
+       * gnus.el: 0.31 is released
+
+Thu Mar  2 01:57:30 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-refer-article-method): New variable.
+       (gnus-summary-refer-article): Use it.
+       (gnus-find-method-for-group): Use the results of the usage. 
+       (gnus-request-article-this-buffer): Use it even more.
+       (gnus-group-mode-map): make-directory-group and make-doc-group
+       have moved.
+       (gnus-group-make-doc-group): Check whether the doc group exists
+       before creating it.
+       (gnus-group-make-kiboze-group): New command and keystroke.
+
+       * nnfolder.el: New one-file one-group mail backend.
+
+       * nnmail.el (nnmail-move-inbox): Would occationally kill a random
+       buffer. Just to keep the users on their toes. Just for the heck of
+       it. 
+
+       * nnvirtual.el (nnvirtual-create-mapping): Would barf if component
+       groups were unactivated.
+       (nnvirtual-retrieve-headers): Would deliver incorrect Xrefs if
+       component groups were foreign.
+
+       * gnus.el (gnus-summary-insert-pseudos): Use the `not-confirm'
+       value of gnus-view-pseudos.
+       (gnus-group-suspend): Don't kill the dribble buffer.
+
+Wed Mar  1 20:58:35 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-save-newsrc-file): Would bug after suspending.
+
+Wed Mar  1 17:01:49 1995  Lars Magne Ingebrigtsen  <larsi@visbur.ifi.uio.no>
+
+       * gnus.el (gnus-article-remove-cr): Didn't set read-only to nil.
+       (gnus-browse-foreign-server): Ignore the groups that should be
+       ignored. 
+
+       * nnspool.el (nnspool-retrieve-headers-with-nov): Misplaced paren.
+       (nnspool-nov-directory): New variable.
+       (nnspool-retrieve-headers-with-nov): Use variable.
+
+       * gnus.el (gnus-inews-domain-name): Try to guess the domain name
+       from (system-name) if all else fails.
+       (gnus-score-find-bnews): Get even that trailing "/" deleted from
+       the kill file dir name.
+
+Wed Mar  1 17:01:25 1995  Lars Magne Ingebrigtsen  <larsi@mimir.ifi.uio.no>
+
+       * gnus.el: 0.30 is released.
+
 Wed Mar  1 00:16:38 1995  Lars Ingebrigtsen  <lars@eyesore.no>
 
        * gnus.el (gnus-inews-unique-id): New message-id look.
index c085bde..ff0a0ff 100644 (file)
@@ -58,7 +58,7 @@ all:  nntp virtual nnmbox nnml nnmh nnspool mh
 # all: elc info
 
 elc:
-       $(EMACS) -batch -l ./dgnushack.el -f dgnushack -f batch-byte-compile *.el
+       $(EMACS) -batch -l ./dgnushack.el -f batch-byte-compile *.el
 
 info:
        cd ../texi; makeinfo gnus.texi
index 57597cc..3e22460 100644 (file)
@@ -1,9 +1,35 @@
+;;; dgnushack --- a hack to set the load path for byte-compiling
+;; Copyright (C) 1994,95 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Version: 4.19
+;; Keywords: news, path
+
+;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; Commentary:
+
 ;; Is this really the only way to set the load path? Seems awfully
-;; kludgy to load this file and run this function just to do something
-;; as simple as that... Anyways, it won't be in the production code,
-;; so who cares?
+;; kludgy to load this file just to do something as simple as
+;; that... Anyways, it won't be in the production code, so who cares?
+
+;;; Code:
+
+(setq load-path (cons "." load-path))
 
-(defun dgnushack () 
-  (setq load-path (cons "." load-path)))
-  
+;;; dgnushack.el ends here  
 
index 9e94353..2879761 100644 (file)
@@ -39,12 +39,33 @@ that. This "newsgroup" is intended as a kinder, gentler way of getting
 people started.
 
 (ding) Gnus is a rewrite of GNUS 4.1, written by Masanobu Umeda. The
-rewrite was done by moi, yours truly, your humle servant, Lars Magne
+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 "http://www.ifi.uio.no/~larsi/larsi.html". 
 
 Much code (especially the score code) was written by Per Abrahamsen. 
 
+;; Copyright (C) 1995 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
 From lars Thu Feb 23 23:20:38 1995
 From: larsi@ifi.uio.no (ding)
 Date: Fri Feb 24 13:40:45 1995
@@ -184,7 +205,12 @@ In particular, `gnus-newsrc-hashtb', `gnus-newsrc-assoc',
 have all changed. If you have some code lying around that depend on
 these, or change these, you'll have to re-write your code.
 
-The old hilit code, for instance, will fail with (ding) Gnus.
+Old hilit19 code does not work at all.  In fact, you should probably
+remove all hihit code from all the Gnus hooks
+(`gnus-group-prepare-hook', `gnus-summary-prepare-hook' and
+`gnus-summary-article-hook').  (Well, at the very least the first
+two.)  Gnus provides various integrated functions for highlighting,
+which are both faster and more accurated.
 
 There is absolutely no chance, whatsoever, of getting Gnus to work
 with Emacs 18.
@@ -213,8 +239,8 @@ If I am not able to reproduce the bug, I won't be able to fix it.
 I would, of course, prefer that you locate the bug, fix it, and mail
 me the patches, but one can't have everything.
 
-If you have any questions on usage, the "gnu.emacs.gnus" newsgroup or
-the "ding@ifi.uio.no" mailing list is where to post the questions. 
+If you have any questions on usage, the "ding@ifi.uio.no" mailing list
+is where to post the questions.
 
 
 From lars Thu Feb 23 23:20:38 1995
@@ -279,9 +305,9 @@ the lines of:
 (setq gnus-select-group-hook
       (lambda ()
        (if (eq 'nnvirtual (car (gnus-find-method-for-group 
-                                 gnus-newsgroup-name)))
+                                 gnus-newsgroup-name)))
            (progn
-             (make-local-variable gnus-thread-sort-functions)
+             (make-local-variable 'gnus-thread-sort-functions)
              (setq gnus-thread-sort-functions '(gnus-thread-sort-by-date))))))
 
 
index 67fded4..9281019 100644 (file)
@@ -2,7 +2,7 @@
 ;; Copyright (C) 1994,95 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
index 314c180..e6c8046 100644 (file)
@@ -1,7 +1,7 @@
 ;;; gnus-uu.el --- extract (uu)encoded files in Gnus
 ;; Copyright (C) 1985,86,87,93,94,95 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Created: 2 Oct 1993
 ;; Version: v3.0
 ;; Keyword: news
@@ -253,6 +253,7 @@ so I simply dropped them.")
 (defconst gnus-uu-output-buffer-name "*Gnus UU Output*")
 
 (defconst gnus-uu-highest-article-number 1)
+(defvar gnus-uu-default-dir default-directory)
 
 ;; Commands.
 
@@ -263,7 +264,11 @@ so I simply dropped them.")
 
 (defun gnus-uu-decode-uu-and-save (n dir)
   "Decodes and saves the resulting file."
-  (interactive "P\nDWhere do you want to save the file(s)? ")
+  (interactive
+   (list current-prefix-arg
+        (read-file-name "Where do you want to save the file(s)? "
+                        gnus-uu-default-dir
+                        gnus-uu-default-dir t)))
   (gnus-uu-decode-with-method 'gnus-uu-uustrip-article n dir))
 
 (defun gnus-uu-decode-unshar (n)
@@ -273,12 +278,20 @@ so I simply dropped them.")
 
 (defun gnus-uu-decode-unshar-and-save (n dir)
   "Unshars and saves the current article."
-  (interactive "P\nDWhere do you want to save the file(s)? ")
+  (interactive
+   (list current-prefix-arg
+        (read-file-name "Where do you want to save the file(s)? "
+                        gnus-uu-default-dir
+                        gnus-uu-default-dir t)))
   (gnus-uu-decode-with-method 'gnus-uu-unshar-article n dir))
 
 (defun gnus-uu-decode-save (n file)
   "Saves the current article."
-  (interactive "P\nDWhere do you want to save the file(s)? ")
+  (interactive
+   (list current-prefix-arg
+        (read-file-name "Where do you want to save the file? "
+                        gnus-uu-default-dir
+                        gnus-uu-default-dir)))
   (setq gnus-uu-saved-article-name file)
   (gnus-uu-decode-with-method 'gnus-uu-save-article n nil)
   (setq gnus-uu-generated-file-list 
@@ -286,43 +299,61 @@ so I simply dropped them.")
 
 (defun gnus-uu-decode-binhex (n dir)
   "Unbinhexes the current article."
-  (interactive "P\nDWhere do you want to save the file(s)? ")
+  (interactive
+   (list current-prefix-arg
+        (read-file-name "Where do you want to save the file(s)? "
+                        gnus-uu-default-dir
+                        gnus-uu-default-dir t)))
   (gnus-uu-decode-with-method 'gnus-uu-binhex-article n dir))
 
 (defun gnus-uu-decode-uu-view (n)
   "Uudecodes and views the current article."    
   (interactive "P")
-  (let ((gnus-view-pseudos 'automatic))
+  (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-uu n)))
 
 (defun gnus-uu-decode-uu-and-save-view (n dir)
   "Decodes, views and saves the resulting file."
-  (interactive "P\nDWhere do you want to save the file(s)? ")
-  (let ((gnus-view-pseudos 'automatic))
+  (interactive
+   (list current-prefix-arg
+        (read-file-name "Where do you want to save the file(s)? "
+                        gnus-uu-default-dir
+                        gnus-uu-default-dir t)))
+  (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-uu-and-save n dir)))
 
 (defun gnus-uu-decode-unshar-view (n)
   "Unshars and views the current article."
   (interactive "P")
-  (let ((gnus-view-pseudos 'automatic))
+  (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-unshar n)))
 
 (defun gnus-uu-decode-unshar-and-save-view (n dir)
   "Unshars and saves the current article."
-  (interactive "P\nDWhere do you want to save the file(s)? ")
-  (let ((gnus-view-pseudos 'automatic))
+  (interactive
+   (list current-prefix-arg
+        (read-file-name "Where do you want to save the file(s)? "
+                        gnus-uu-default-dir
+                        gnus-uu-default-dir t)))
+  (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-unshar-and-save n dir)))
 
 (defun gnus-uu-decode-save-view (n file)
   "Saves and views the current article."
-  (interactive "P\nDWhere do you want to save the file(s)? ")
-  (let ((gnus-view-pseudos 'automatic))
+  (interactive
+   (list current-prefix-arg
+        (read-file-name "Where do you want to save the file? "
+                        gnus-uu-default-dir gnus-uu-default-dir)))
+  (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-save n file)))
 
 (defun gnus-uu-decode-binhex-view (n file)
   "Unbinhexes and views the current article."
-  (interactive "P\nDWhere do you want to save the file(s)? ")
-  (let ((gnus-view-pseudos 'automatic))
+  (interactive
+   (list current-prefix-arg
+        (read-file-name "Where do you want to save the file(s)? "
+                        gnus-uu-default-dir gnus-uu-default-dir)))
+  (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-binhex n file)))
 
 
@@ -426,6 +457,7 @@ so I simply dropped them.")
 
 (defun gnus-uu-decode-with-method (method n &optional save)
   (gnus-uu-initialize)
+  (if save (setq gnus-uu-default-dir save))
   (let ((articles (gnus-uu-get-list-of-articles n))
        files)
     (setq files (gnus-uu-grab-articles articles method t))
@@ -442,7 +474,8 @@ so I simply dropped them.")
       (setq file (cdr (assq 'name (car files))))
       (copy-file file (if (file-directory-p dir)
                          (concat dir (file-name-nondirectory file))
-                       dir))
+                       dir)
+                t)
       (setq files (cdr files)))
     (message "Saved %d file%s" len (if (> len 1) "s" ""))))
 
@@ -866,7 +899,8 @@ so I simply dropped them.")
        (setq article-buffer gnus-article-buffer))
 
       (buffer-disable-undo article-buffer)
-      (gnus-summary-mark-as-read article)
+      ;; Mark article as read.
+      (run-hooks 'gnus-mark-article-hook)
       (and (memq article gnus-newsgroup-processable)
           (gnus-summary-remove-process-mark article))
 
@@ -929,7 +963,6 @@ so I simply dropped them.")
            (erase-buffer)
            (insert-buffer-substring article-buffer)
            (goto-char 1))))
-    (run-hooks 'gnus-mark-article-hook)
 
     (if result-files
        ()
index eca0e31..72d27f9 100644 (file)
@@ -1,7 +1,7 @@
 ;;; gnus-visual: display-oriented parts of Gnus.
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -51,6 +51,9 @@ To check for marks, e.g. to underline replied articles, use `looking-at':
 This will match all lines where the second character is `R'.  
 The `.' will match any character.")
 
+(eval-and-compile
+  (autoload 'nnkiboze-generate-groups "nnkiboze"))
+
 ;; Newsgroup buffer
 
 ;; Make a menu bar item.
@@ -62,15 +65,16 @@ The `.' will match any character.")
    '("Group"
      ["Read" gnus-group-read-group t]
      ["Select" gnus-group-select-group t]
-     ["Mark unread articles as read" gnus-group-catchup-current t]
-     ["Mark all unread articles as read" gnus-group-catchup-current-all t]
+     ["Catch up" gnus-group-catchup-current t]
+     ["Catch up all articles" gnus-group-catchup-current-all t]
      ["Check for new articles" gnus-group-get-new-news-this-group t]
      ["Toggle subscription" gnus-group-unsubscribe-current-group t]
      ["Kill" gnus-group-kill-group t]
      ["Yank" gnus-group-yank-group t]
      ["Describe" gnus-group-describe-group t]
+     ["Fetch FAQ" gnus-group-fetch-faq t]
      ["Edit kill file" gnus-group-edit-local-kill t]
-     ["Expire expirable articles" gnus-group-expire-articles t]
+     ["Expire articles" gnus-group-expire-articles t]
      ["Set group level" gnus-group-set-current-level t]
      ))
   
@@ -84,14 +88,17 @@ The `.' will match any character.")
      ["List subscribed groups" gnus-group-list-groups t]
      ["List all groups" gnus-group-list-all-groups t]
      ["List groups matching..." gnus-group-list-matching t]
+     ["Sort group buffer" gnus-group-sort-groups t]
      ["Subscribe to random group" gnus-group-unsubscribe-group t]
      ["Describe all groups" gnus-group-describe-all-groups t]
      ["Group apropos" gnus-group-apropos t]
      ["Group and description apropos" gnus-group-description-apropos t]
-     ["Add a foreign group" gnus-group-add-newsgroup t]
-     ["Edit a group entry" gnus-group-edit-newsgroup t]
+     ["List groups matching..." gnus-group-list-matching t]
+     ["Add a foreign group" gnus-group-add-group t]
+     ["Edit a group entry" gnus-group-edit-group t]
      ["Add a directory group" gnus-group-make-directory-group t]
-     ["Add the documentation group" gnus-group-make-doc-group t]
+     ["Add the help group" gnus-group-make-help-group t]
+     ["Make a kiboze group" gnus-group-make-kiboze-group t]
      ["Kill all newsgroups in region" gnus-group-kill-region t]
      ["Kill all zombie groups" gnus-group-kill-all-zombies t]
      ["List killed groups" gnus-group-list-killed t]
@@ -120,13 +127,14 @@ The `.' will match any character.")
      ["Read init file" gnus-group-read-init-file t]
      ["Browse foreign server" gnus-group-browse-foreign-server t]
      ["Edit the global kill file" gnus-group-edit-global-kill t]
-     ["Expire expirable articles in all groups" gnus-group-expire-all-groups t]
+     ["Expire all expirable articles" gnus-group-expire-all-groups t]
+     ["Generate any kiboze groups" nnkiboze-generate-groups t]
      ["Gnus version" gnus-version t]
      ["Save .newsrc files" gnus-group-save-newsrc t]
      ["Suspend Gnus" gnus-group-suspend t]
      ["Clear dribble buffer" gnus-group-clear-dribble t]
      ["Exit from Gnus" gnus-group-exit t]
-     ["Exit from Gnus without updating .newsrc" gnus-group-quit t]
+     ["Exit without saving" gnus-group-quit t]
      ))
 
   )
@@ -142,14 +150,11 @@ The `.' will match any character.")
      ["Tick" gnus-summary-tick-article-forward t]
      ["Mark as read" gnus-summary-mark-as-read-forward t]
      ["Mark as unread" gnus-summary-clear-mark-forward t]
-     ["Mark all articles with the current subject as read and select"
-      gnus-summary-kill-same-subject-and-select t]
-     ["Mark all articles with the current subject as read"
-      gnus-summary-kill-same-subject t]
-     ["Delete all subjects marked as read" gnus-summary-delete-marked-as-read t]
-     ["Delete all subjects marked with..." gnus-summary-delete-marked-with t]
+     ["Mark same subject and select" gnus-summary-kill-same-subject-and-select t]
+     ["Mark same subject" gnus-summary-kill-same-subject t]
+     ["Remove lines marked as read" gnus-summary-remove-lines-marked-as-read t]
+     ["Remove lines marked with..." gnus-summary-remove-lines-marked-with t]
      ["Set expirable mark" gnus-summary-mark-as-expirable t]
-     ["Remove expirable mark" gnus-summary-unmark-as-expirable t]
      ["Set bookmark" gnus-summary-set-bookmark t]
      ["Remove bookmark" gnus-summary-remove-bookmark t]
      ["Catchup" gnus-summary-catchup t]
@@ -167,6 +172,7 @@ The `.' will match any character.")
       ["Mark by regexp" gnus-uu-mark-by-regexp t]
       ["Mark all" gnus-uu-mark-all t]
       ["Mark sparse" gnus-uu-mark-sparse t]
+      ["Mark thread" gnus-uu-mark-thread t]
       )
      ))
 
@@ -180,11 +186,12 @@ The `.' will match any character.")
      ["Previous unread article" gnus-summary-prev-unread-article t]
      ["Next article" gnus-summary-next-article t]
      ["Previous article" gnus-summary-prev-article t]
-     ["Next article with the same subject" gnus-summary-next-same-subject t]
-     ["Previous article with the same subject" gnus-summary-prev-same-subject t]
-     ["Go to the first unread article" gnus-summary-first-unread-article t]
+     ["Next article same subject" gnus-summary-next-same-subject t]
+     ["Previous article same subject" gnus-summary-prev-same-subject t]
+     ["First unread article" gnus-summary-first-unread-article t]
      ["Go to subject number..." gnus-summary-goto-subject t]
-     ["Go to the previous article" gnus-summary-goto-last-article t]
+     ["Go to the last article" gnus-summary-goto-last-article t]
+     ["Pop article off history" gnus-summary-pop-article t]
      ))
 
   (easy-menu-define
@@ -197,26 +204,36 @@ The `.' will match any character.")
       ["Signature" gnus-article-hide-signature t]
       ["Citation" gnus-article-hide-citation t]
       ["Overstrike" gnus-article-treat-overstrike t]
-      ["Word Wrap" gnus-article-word-wrap t]
+      ["Word wrap" gnus-article-word-wrap t]
       ["CR" gnus-article-remove-cr t]
       ["Quoted-Printable" gnus-article-de-quoted-unreadable t])
-     ["Interactive search in the article" gnus-summary-isearch-article t]
-     ["Search for an regexp in articles" gnus-summary-search-article-forward t]
+     ("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])
+     ["Enter digest buffer" gnus-summary-enter-digest-group t]
+     ["Isearch article" gnus-summary-isearch-article t]
+     ["Search all articles" gnus-summary-search-article-forward t]
      ["Beginning of the article" gnus-summary-beginning-of-article t]
      ["End of the article" gnus-summary-end-of-article t]
-     ["Fetch the parent of the article" gnus-summary-refer-parent-article t]
-     ["Fetch an article with Message-ID..." gnus-summary-refer-article t]
+     ["Fetch parent of article" gnus-summary-refer-parent-article t]
+     ["Fetch article with id..." gnus-summary-refer-article t]
      ["Stop page breaking" gnus-summary-stop-page-breaking t]
      ["Caesar rotate" gnus-summary-caesar-message t]
      ["Redisplay" gnus-summary-show-article t]
      ["Toggle header" gnus-summary-toggle-header t]
      ["Toggle MIME" gnus-summary-toggle-mime t]
      ["Save" gnus-summary-save-article t]
-     ["Save in rmail format" gnus-summary-save-article-rmail t]
+     ["Save in mail format" gnus-summary-save-article-mail t]
      ["Pipe through a filter" gnus-summary-pipe-output t]
-     ["Respool article" gnus-summary-respool-article t]
-     ["Move article" gnus-summary-move-article t]
-     ["Edit article" gnus-summary-edit-article t]
+     ("Mail articles"
+      ["Respool article" gnus-summary-respool-article t]
+      ["Move article" gnus-summary-move-article t]
+      ["Edit article" gnus-summary-edit-article t]
+      ["Delete article" gnus-summary-delete-article t])
      ))
 
   (easy-menu-define
@@ -241,17 +258,19 @@ The `.' will match any character.")
    gnus-summary-mode-map
    ""
    '("Misc"
-     ["Sort by number" gnus-summary-sort-by-number t]
-     ["Sort by author" gnus-summary-sort-by-author t]
-     ["Sort by subject" gnus-summary-sort-by-subject t]
-     ["Sort by date" gnus-summary-sort-by-date t]
+     ("Sort"
+      ["Sort by number" gnus-summary-sort-by-number t]
+      ["Sort by author" gnus-summary-sort-by-author t]
+      ["Sort by subject" gnus-summary-sort-by-subject t]
+      ["Sort by date" gnus-summary-sort-by-date t])
+     ["Fetch group FAQ" gnus-summary-fetch-faq t]
      ["Filter articles" gnus-summary-execute-command t]
-     ["Mark all articles as read and exit" gnus-summary-catchup-and-exit t]
+     ["Mark all read and exit" gnus-summary-catchup-and-exit t]
      ["Toggle line truncation" gnus-summary-toggle-truncation t]
      ["Expire expirable articles" gnus-summary-expire-articles t]
-     ["Delete a mail article" gnus-summary-delete-article t]
-     ["Show all dormant articles" gnus-summary-show-all-dormant t]
-     ["Show all expunged articles" gnus-summary-show-all-expunged t]
+     ["Show dormant articles" gnus-summary-show-all-dormant t]
+     ["Hide dormant articles" gnus-summary-hide-all-dormant t]
+     ["Show expunged articles" gnus-summary-show-all-expunged t]
      ["Reselect group" gnus-summary-reselect-current-group t]
      ["Rescan group" gnus-summary-rescan-group t]
      ["Describe group" gnus-summary-describe-group t]
@@ -265,17 +284,18 @@ The `.' will match any character.")
    ""
    '("Post"
      ["Post an article" gnus-summary-post-news t]
-     ["Followup an article" gnus-summary-followup t]
-     ["Followup an article and include original" 
-      gnus-summary-followup-with-original t]
+     ["Followup" gnus-summary-followup t]
+     ["Followup and yank" gnus-summary-followup-with-original t]
      ["Supersede article" gnus-summary-supersede-article t]
      ["Cancel article" gnus-summary-cancel-article t]
-     ["Mail a reply" gnus-summary-reply t]
-     ["Mail a reply and include original" gnus-summary-reply-with-original t]
-     ["Forward an article via mail" gnus-summary-mail-forward t]
+     ["Reply" gnus-summary-reply t]
+     ["Reply and yank" gnus-summary-reply-with-original t]
+     ["Forward" gnus-summary-mail-forward t]
+     ["Digest and forward" gnus-uu-digest-and-forward t]
      ["Send a mail" gnus-summary-mail-other-window t]
-     ["Send a reply and a followup" gnus-summary-followup-and-reply t]
-     ["Send a reply and a followup and include original" gnus-summary-followup-and-reply-with-original t]
+     ["Reply & followup" gnus-summary-followup-and-reply t]
+     ["Reply & followup and yank" gnus-summary-followup-and-reply-with-original t]
+     ["Uuencode and post" gnus-uu-post-news t]
      ))
 
   (easy-menu-define
@@ -285,8 +305,8 @@ The `.' will match any character.")
    '("Kill"
      ["Edit local kill file" gnus-summary-edit-local-kill t]
      ["Edit global kill file" gnus-summary-edit-global-kill t]
-     ["Expunge with score below..." gnus-kill-file-set-expunge-below t]
-     ["Set mark with score below..." gnus-kill-file-set-mark-below t]
+     ["Expunge with score below..." gnus-score-set-expunge-below t]
+     ["Set mark with score below..." gnus-score-set-mark-below t]
      ["Raise score with current subject" 
       gnus-summary-temporarily-raise-by-subject t]
      ["Raise score with current author" 
@@ -375,19 +395,23 @@ The `.' will match any character.")
 (defun gnus-visual-summary-highlight-line ()
   "Highlight current line according to `gnus-visual-summary-highlight'."
   (let ((list gnus-visual-summary-highlight)
+       (score (gnus-summary-article-score))
+       (default gnus-summary-default-score)
        (inhibit-read-only t))
-    (while (and list (not (eval (car (car list)))))
-      (setq list (cdr list)))
-    (let ((face (and list (cdr (car list)))))
-      (save-excursion
-       ;; BUG! For some reason the text properties of the first
-       ;; characters get mangled. 
-       (forward-char 10)
-       (if (eq face (get-text-property (point) 'face))
-           ()
-         (put-text-property (save-excursion (beginning-of-line 1) (point))
-                            (save-excursion (end-of-line 1) (point))
-                            'face face))))))
+    (save-excursion
+      (beginning-of-line)
+      (while (and list (not (eval (car (car list)))))
+       (setq list (cdr list)))
+      (let ((face (and list (cdr (car list)))))
+       (save-excursion
+         ;; BUG! For some reason the text properties of the first
+         ;; characters get mangled. 
+         (forward-char 10)
+         (if (eq face (get-text-property (point) 'face))
+             ()
+           (put-text-property (save-excursion (beginning-of-line 1) (point))
+                              (save-excursion (end-of-line 1) (point))
+                              'face face)))))))
 
 (provide 'gnus-visual)
 
index 1f58d3d..601a320 100644 (file)
@@ -2,7 +2,7 @@
 ;; Copyright (C) 1987,88,89,90,93,94,95 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -51,8 +51,8 @@
        "nntp")
   "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, and the optional
-third element is the \"port number\", if nntp is used.
+news is to be fetched, the second is the address.  An optional third
+element can be included to specify a port number if nntp is used.
 
 For instance, if you want to get your news via NNTP from
 \"flab.flab.edu\" on port 23, you could say:
@@ -68,7 +68,7 @@ If you use this variable, you must set `gnus-nntp-server' to nil.")
 ;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>.
 (defvar gnus-post-method nil
   "Preferred method for posting USENET news.
-If this variable is nil, GNUS will use the current method to decide
+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.
@@ -76,15 +76,24 @@ the like, only in \"real\" newsgroups.
 The value must be a valid method as discussed in the documentation of
 `gnus-select-method'.")
 
+(defvar gnus-refer-article-method nil
+  "Preferred method for fetching an article by Message-ID.
+If you are reading news from the local spool (with nnspool), fetching
+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'")
+
 (defvar gnus-secondary-select-methods nil
-  "A list of secondary methods that will be used for reading news.")
+  "A list of secondary methods that will be used for reading news.
+This is a list where each element is a complete select methdod (see
+`gnus-select-method').  
 
-(defvar gnus-default-nntp-server nil
-  "Specify a default NNTP server.
-This variable should be defined in paths.el, and should never be set
-by the user.
-If you want to change servers, you should use `gnus-select-method'.
-See the documentation to that variable.")
+If, for instance, you want to read your mail with the nnml backend,
+you could set this variable:
+
+(setq gnus-secondary-select-methods '((nnml ""))")
 
 (defvar gnus-secondary-servers nil
   "List of NNTP servers that the user can choose between interactively.
@@ -92,7 +101,7 @@ To make Gnus query you for a server, you have to give `gnus' a
 non-numeric prefix - `C-u M-x gnus', in short.")
 
 (defvar gnus-nntp-server nil
-  "*The name of the host running the NNTP server.
+  "The name of the host running the NNTP server.
 This variable is semi-obsolete. Use the `gnus-select-method'
 variable instead.")
 
@@ -102,10 +111,11 @@ This is an obsolete variable, which is scarcely used. If you use an
 nntp server for your newsgroup and want to change the port number
 used to 899, you would say something along these lines:
 
-(setq gnus-select-method '(nntp \"my.nntp.server\" 899))")
+ (setq gnus-select-method '(nntp \"my.nntp.server\" 899))")
 
 (defvar gnus-startup-file "~/.newsrc"
-  "Your `.newsrc' file.  Use `.newsrc-SERVER' instead if it exists.")
+  "Your `.newsrc' file.
+`.newsrc-SERVER' will be used instead if that exists.")
 
 (defvar gnus-signature-file "~/.signature"
   "Your signature file.
@@ -123,23 +133,24 @@ be used instead.")
 
 (defvar gnus-init-file "~/.gnus"
   "Your Gnus elisp startup file.
-If a file with the .el or .elc suffixes exist, they will be read
+If a file with the .el or .elc suffixes exist, it will be read
 instead.") 
 
+(defvar gnus-group-faq-directory "/ftp@rtfm.mit.edu:/pub/usenet-by-group/"
+  "Directory where the group FAQs are stored.
+This will most commonly be on a remote machine, and the file will be
+fetched by ange-ftp.")
+
 (defvar gnus-default-subscribed-newsgroups nil
   "This variable lists what newsgroups should be susbcribed the first time Gnus is used.
 It should be a list of strings.
 If it is `t', Gnus will not do anything special the first time it is
 started; it'll just use the normal newsgroups subscription methods.")
 
-(defconst gnus-backup-default-subscribed-newsgroups 
-  '("news.announce.newusers" "news.groups.questions" "gnu.emacs.gnus")
-  "Default default new newsgroups the first time Gnus is run.")
-
 (defvar gnus-post-prepare-function nil
   "Function that is run after a post buffer has been prepared.
 It is called with the name of the newsgroup that is posted to. It
-might be use, for instance, for inserting signatures based on the
+might be used, for instance, for inserting signatures based on the
 newsgroup name. (In that case, `gnus-signature-file' and
 `mail-signature' should both be set to nil).")
 
@@ -157,7 +168,8 @@ information can be restored from the dribble file.")
 (defvar gnus-use-followup-to 'use
   "Specifies what to do with Followup-To header.
 If nil, ignore the header. If it is t, use its value, but ignore 
-`poster'. If it is neither nil nor t, always use the value.")
+`poster'. If it is neither nil nor t, which is the default, always use
+the value.") 
 
 (defvar gnus-followup-to-function nil
   "A variable that contains a function that returns a followup address.
@@ -185,33 +197,37 @@ this variable is used.")
 
 (defvar gnus-large-newsgroup 200
   "The number of articles which indicates a large newsgroup.
-If the number of articles in a newsgroup is greater than the value,
+If the number of articles in a newsgroup is greater than this value,
 confirmation is required for selecting the newsgroup.")
 
 (defvar gnus-author-copy (getenv "AUTHORCOPY")
-  "Name of the file the article will be saved before it is posted using the FCC header.
+  "Save outgoing articles in this file.
 Initialized from the AUTHORCOPY environment variable.
 
-Articles are saved using a function specified by the the variable
-`gnus-author-copy-saver' (`rmail-output' is default) if a file name is
-given.  Instead, if the first character of the name is `|', the
-contents of the article is piped out to the named program. It is
-possible to save an article in an MH folder as follows:
+If this variable begins with the character \"|\", outgoing articles
+will be piped to the named program. It is possible to save an article
+in an MH folder as follows:
+
+\(setq gnus-author-copy \"|/usr/local/lib/mh/rcvstore +Article\")
 
-\(setq gnus-author-copy \"|/usr/local/lib/mh/rcvstore +Article\")")
+If the first character is not a pipe, articles are saved using the
+function specified by the `gnus-author-copy-saver' variable.")
 
 (defvar gnus-mail-self-blind nil
-  "Non-nil means insert BCC to self in messages to be sent.
-This is done when the message is initialized,
-so you can remove or alter the BCC header to override the default.")
+  "Non-nil means insert a BCC header in all outgoing articles.
+This will result in having a copy of the article mailed to yourself.
+The BCC header is inserted when the post buffer is initialized, so you
+can remove or alter the BCC header to override the default.")
 
 (defvar gnus-author-copy-saver (function rmail-output)
-  "A function called with a file name to save an author copy to.
-The default function is `rmail-output' which saves in Unix mailbox format.")
+  "A function called to save outgoing articles.
+This function will be called with the same of the file to store the
+article in. The default function is `rmail-output' which saves in Unix
+mailbox format.")
 
 (defvar 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 newsgroup name.
-If it's nil, the directory form of the newsgroup name is used instead.")
+  "Non-nil means that the default name of a file to save articles in is the group name.
+If it's nil, the directory form of the group name is used instead.")
 
 (defvar gnus-article-save-directory (or (getenv "SAVEDIR") "~/News/")
   "Name of the directory articles will be saved in (default \"~/News\").
@@ -221,8 +237,8 @@ Initialized from the SAVEDIR environment variable.")
   "Name of the directory where kill files will be stored (default \"~/News\").
 Initialized from the SAVEDIR environment variable.")
 
-(defvar gnus-kill-expiry-days 7
-  "*Number of days before unused kill file entries are expired.")
+(defvar gnus-score-expiry-days 7
+  "*Number of days before unused score file entries are expired.")
 
 (defvar gnus-default-article-saver (function gnus-summary-save-in-rmail)
   "A function to save articles in your favorite format.
@@ -255,21 +271,25 @@ The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
 (defvar gnus-kill-file-name "KILL"
   "Suffix of the kill files.")
 
+(defvar gnus-score-file-suffix "SCORE"
+  "Suffix of the score files.")
+
 (defvar gnus-fetch-old-headers nil
   "Non-nil means that Gnus will try to build threads by grabbing old headers.
 If an unread article in the group refers to an older, already read (or
 just marked as read) article, the old article will not normally be
-displayed in the Summary buffer. If this variable is non-nil, Gnus
+displayed in the Summary buffer.  If this variable is non-nil, Gnus
 will attempt to grab the headers to the old articles, and thereby
-build complete threads. `gnus-nov-is-evil' has to be nil if this is
-to work.  If it has the value `some', only enough headers to connect
-otherwise loose threads will be displayed.")
+build complete threads.  If it has the value `some', only enough
+headers to connect otherwise loose threads will be displayed.
+
+The server has to support XOVER for any of this to work.")
 
 (defvar gnus-visual t
   "*If non-nil, will do various highlighting.
-If nil, no mouse highlight (or any other) will be performed. This
-might speed up Gnus some when generating large group and summary
-buffers.")
+If nil, no mouse highlights (or any other highlights) will be
+performed.  This might speed up Gnus some when generating large group
+and summary buffers.")
 
 (defvar gnus-novice-user t
   "*Non-nil means that you are a usenet novice.
@@ -313,11 +333,25 @@ have all the sub-threads as children.
 If this variable is `adopt', Gnus will make one of the \"children\"
 the parent and mark all the step-children as such.
 If this variable is `empty', the \"children\" are printed with empty
-subject fields.")
+subject fields.  (Or rather, they will be printed with a string
+given by the `gnus-summary-same-subject' variable.)")
 
 (defvar gnus-summary-gather-subject-limit nil
-  "*Maximum length of subject to compare when gathering loose threads.
-Use nil to compare the whole subject.")
+  "*Maximum length of subject comparisons when gathering loose threads.
+Use nil to compare full subjects.  Setting this variable to a low
+number will help gather threads that have been corrupted by
+newsreaders chopping off subject lines, but it might also mean that
+unrelated articles that have subject that happen to begin with the
+same few characters will be incorrectly gathered.")
+
+;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
+(defvar gnus-summary-same-subject ""
+  "String indicating that the current article has the same subject as the previous.
+This variable will only be used if the value of
+`gnus-summary-make-false-root' is `empty'.")
+
+(defvar gnus-summary-goto-unread nil
+  "If non-nil, marking commands will go to the next unread article.")
 
 (defvar gnus-check-new-newsgroups t
   "Non-nil means that Gnus will add new newsgroups at startup.
@@ -325,8 +359,9 @@ If this variable is `ask-server', Gnus will ask the server for new
 groups since the last time it checked. This means that the killed list
 is no longer necessary, so you could set `gnus-save-killed-list' to
 nil. 
-A variant is to have this variable be a list of select methods. Then
-Gnus will use the `ask-server' method on all these select methods to
+
+A variant is to have this variable be a list of select methods. Gnus
+will then use the `ask-server' method on all these select methods to
 query for new groups from all those servers.
 
 Eg.
@@ -355,48 +390,67 @@ subscribed newsgroups, but not the rest, you'd set this variable to 5.
 If you subscribe to lots of newsgroups from different servers, startup
 might take a while. By setting this variable to nil, you'll save time,
 but you won't be told how many unread articles there are in the
-newsgroups.")
+groups.")
 
 (defvar gnus-save-newsrc-file t
-  "Non-nil means that Gnus will save a .newsrc file.
-Gnus always saves its own startup file, which is called \".newsrc.el\".
-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 exit.")
+  "Non-nil means that Gnus will save the `.newsrc' file.
+Gnus always saves 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
+exit.")
 
 (defvar gnus-save-killed-list t
   "If non-nil, save the list of killed groups to the startup file.
-This will save both time (when starting and quitting) and space (on
-disk), but it will also mean that Gnus has no record of what
-newsgroups are new or old, so the automatic new newsgroups
-subscription methods become meaningless. You should always set
-`gnus-check-new-newsgroups' to nil if you set this variable to nil.") 
+This will save both time (when starting and quitting) and space (both
+memory and disk), but it will also mean that Gnus has no record of
+which groups are new and which are old, so the automatic new
+newsgroups subscription methods become meaningless. You should always
+set `gnus-check-new-newsgroups' to `ask-server' or nil if you set this
+variable to nil.")
 
 (defvar gnus-interactive-catchup t
-  "Require your confirmation when catching up a newsgroup if non-nil.")
+  "If non-nil, require your confirmation when catching up a group.")
 
 (defvar gnus-interactive-post t
-  "Group and subject will be asked for if non-nil.")
+  "If non-nil, group name will be asked for when posting.")
 
 (defvar gnus-interactive-exit t
-  "Require your confirmation when exiting Gnus if non-nil.")
+  "If non-nil, require your confirmation when exiting Gnus.")
 
 (defvar gnus-kill-killed nil
-  "If non-nil, Gnus will apply kill files to already killd articles.
+  "If non-nil, Gnus will apply kill files to already killed articles.
 If it is nil, Gnus will never apply kill files to articles that have
 already been through the scoring process, which might very well save lots
 of time.")
 
-;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defvar gnus-summary-same-subject ""
-  "String indicating that the current article has the same subject as the previous.")
+(defvar 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
+`mail-extract-address-components', which works much better, but is
+slower.")
 
 (defvar gnus-score-interactive-default-score 1000
-  "Scoring commands will raise/lower with this number as the default.")
+  "Scoring commands will raise/lower the score with this number as the default.")
+
+(defvar gnus-global-score-files nil
+  "List of global score files and directories.
+Set this variable if you want to use people's score files.  One entry
+for each score file or each score file directory.  Gnus will decide
+by itself what score files are applicable to which group.
+
+Say you want to use the single score file
+\"/ftp.ifi.uio.no@ftp:/pub/larsi/ding/score/soc.motss.SCORE\" and all
+score files in the \"/ftp.some-where:/pub/score\" directory.
+
+ (setq gnus-global-score-files
+       '(\"/ftp.ifi.uio.no:/pub/larsi/ding/score/soc.motss.SCORE\"
+         \"/ftp.some-where:/pub/score\"))")
 
 (defvar gnus-summary-default-score 0
   "Default article score level.
-If this variable is nil, score levels will not be used.")
+If this variable is nil, scoring will be disabled.")
 
 (defvar gnus-user-login-name nil
   "The login name of the user.
@@ -407,25 +461,33 @@ Got from the function `user-login-name' if undefined.")
 Got from the NAME environment variable if undefined.")
 
 (defvar gnus-show-mime nil
-  "*Show MIME message if non-nil.")
+  "*If non-ni, do mime processing of articles.
+The articles will simply be fed to the function given by
+`gnus-show-mime-method'.")
+
+(defvar gnus-show-mime-method (function metamail-buffer)
+  "Function to process a MIME message.
+The function is called from the article buffer.")
 
 (defvar gnus-show-threads t
-  "*Show conversation threads in summary mode if non-nil.")
+  "*If non-nil, display threads in summary mode.")
 
 (defvar gnus-thread-hide-subtree nil
-  "Non-nil means hide thread subtrees initially.
-If non-nil, you have to run the command `gnus-summary-show-thread' by
-hand or by using `gnus-select-article-hook' to show hidden threads.")
+  "If non-nil, hide all threads initially.
+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.")
 
 (defvar gnus-thread-hide-killed t
-  "Non-nil means hide killed thread subtrees automatically.")
+  "If non-nil, hide killed threads automatically.")
 
 (defvar gnus-thread-ignore-subject nil
-  "Don't take care of subject differences, but only references if non-nil.
-If it is non-nil, some commands work with subjects do not work properly.")
+  "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.")
 
 (defvar gnus-thread-indent-level 4
-  "Indentation of thread subtrees.")
+  "Number that says how much each sub-thread should be indented.")
 
 ;; jwz: nuke newsgroups whose name is all digits - that means that
 ;; some loser has let articles get into the root of the news spool,
@@ -462,62 +524,71 @@ this list.")
 
 (defvar gnus-required-headers
   '(From Date Newsgroups Subject Message-ID Organization Lines X-Newsreader)
-  ;; changed by jwz because it's not so nice to do "Lines: 0" by default.
-  ;; and to remove Path, since it's incorrect for Gnus to try
-  ;; and generate that - it is the responsibility of inews or nntpd.
-  "All required headers for articles you post.
+  "Headers to be generated or prompted for when posting an article.
 RFC977 and RFC1036 require From, Date, Newsgroups, Subject, Message-ID
 and Path headers.  Organization, Lines and X-Newsreader are optional.
 If you want Gnus not to insert some header, remove it from this
-variable.")
+list.") 
 
 (defvar gnus-show-all-headers nil
-  "*Show all headers of an article if non-nil.")
+  "*If non-nil, don't hide any headers.")
 
 (defvar gnus-save-all-headers t
-  "*Save all headers of an article if non-nil.")
+  "*If non-nil, don't remove any headers before saving.")
 
 (defvar gnus-inhibit-startup-message nil
-  "The startup message will not be displayed if this function is non-nil.")
+  "If non-nil, the startup message will not be displayed.")
 
 (defvar gnus-auto-extend-newsgroup t
-  "Extend visible articles to forward and backward if non-nil.")
+  "If non-nil, extend newsgroup forward and backward when requested.")
 
 (defvar gnus-auto-select-first t
-  "Select the first unread article automagically if non-nil.
+  "If non-nil, select the first unread article when entering a group.
 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'
-or `gnus-apply-kill-hook'.")
+in some newsgroups, set the variable to nil in
+`gnus-select-group-hook'.") 
 
 (defvar gnus-auto-select-next t
-  "Select the next newsgroup automagically if non-nil.
+  "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.  Especially, if
-the value is the symbol `quietly', the next unread newsgroup will be
-selected without any confirmations.")
+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 confirmations.")
 
 (defvar gnus-auto-select-same nil
-  "Select the next article with the same subject automagically if non-nil.")
+  "If non-nil, select the next article with the same subject.")
 
 (defvar gnus-auto-center-summary t
-  "*Always center the current summary in Gnus summary window if non-nil.")
+  "*If non-nil, always center the current summary buffer.")
 
 (defvar gnus-auto-mail-to-author nil
-  "Insert `To: author' of the article when following up if non-nil.
-If this variable is `ask', the user will be prompted.
-Mail is sent using the function specified by the variable
-`gnus-mail-send-method'.")
+  "*If non-nil, mail the authors of articles a copy of your follow-ups.
+If this variable is `ask', the user will be prompted for whether to
+mail a copy.  The string given by `gnus-mail-courtesy-message' will be
+inserted at the beginning of the mail copy.
+
+Mail is sent using the function specified by the
+`gnus-mail-send-method' variable.")
+
+;; Added by Ethan Bradford <ethanb@ptolemy.astro.washington.edu>.
+(defvar gnus-mail-courtesy-message
+  "The following message is a courtesy copy of an article\nthat has been posted as well.\n\n"
+  "This is inserted at the start of a mailed copy of a posted message.
+If this variable is nil, no such courtesy message will be added.")
 
 (defvar gnus-break-pages t
-  "*Break an article into pages if non-nil.
-Page delimiter is specified by the variable `gnus-page-delimiter'.")
+  "*If non-nil, do page breaking on articles.
+The page delimiter is specified by the `gnus-page-delimiter'
+variable.")
 
 (defvar gnus-page-delimiter "^\^L"
-  "Regexp describing line-beginnings that separate pages of news article.")
+  "Regexp describing what to use as article page delimiters.
+The default value is \"^\^L\", which is a form linefeed at the
+beginning of a line.")
 
 (defvar gnus-use-full-window t
-  "*Non-nil means to take up the entire screen of Emacs.")
+  "*If non-nil, use the entire Emacs screen.")
 
 (defvar gnus-window-configuration
   '((summary (0 1 0))
@@ -530,43 +601,34 @@ windows, respectively, or a list of (ACTION FUNCTION), where FUNCTION
 is a function that will be called with ACTION as an argument. ACTION
 can be `summary', `newsgroups', or `article'.")
 
-(defvar gnus-show-mime-method (function metamail-buffer)
-  "Function to process a MIME message.
-The function is expected to process current buffer as a MIME message.")
-
-(defvar gnus-mail-reply-method
-  (function gnus-mail-reply-using-mail)
-  "Function to compose reply mail.
-The function `gnus-mail-reply-using-mail' uses usual sendmail mail
-program.  The function `gnus-mail-reply-using-mhe' uses the MH-E mail
-program.  You can use yet another program by customizing this variable.")
-
-(defvar gnus-mail-forward-method
-  (function gnus-mail-forward-using-mail)
-  "Function to forward current message to another user.
-The function `gnus-mail-reply-using-mail' uses usual sendmail mail
-program.  You can use yet another program by customizing this variable.")
-
-(defvar gnus-mail-other-window-method
-  (function gnus-mail-other-window-using-mail)
-  "Function to compose mail in other window.
-The function `gnus-mail-other-window-using-mail' uses the usual sendmail
-mail program.  The function `gnus-mail-other-window-using-mhe' uses the MH-E
-mail program.  You can use yet another program by customizing this variable.")
+(defvar gnus-mail-reply-method (function gnus-mail-reply-using-mail)
+  "Function to compose a reply.
+Two pre-made functions are `gnus-mail-reply-using-mail' (sendmail) and
+`gnus-mail-reply-using-mhe' (MH-E).")
+
+(defvar gnus-mail-forward-method (function gnus-mail-forward-using-mail)
+  "Function to forward the current message to another user.
+Two pre-made functions are `gnus-mail-forward-using-mail' (sendmail)
+and `gnus-mail-forward-using-mhe' (MH-E).") 
+
+(defvar gnus-mail-other-window-method 'gnus-mail-other-window-using-mail
+  "Function to compose mail in the other window.
+Two pre-made functions are `gnus-mail-other-window-using-mail'
+(sendmail) and `gnus-mail-other-window-using-mhe' (MH-E).")
 
 (defvar gnus-mail-send-method send-mail-function
-  "Function to mail a message too which is being posted as an article.
+  "Function to mail a message which is also being posted as an article.
 The message must have To or Cc header.  The default is copied from
 the variable `send-mail-function'.")
 
-(defvar gnus-subscribe-newsgroup-method
-  (function gnus-subscribe-zombies)
-  "Function called with a newsgroup name when new newsgroup is found.
-The function `gnus-subscribe-randomly' inserts a new newsgroup a the
-beginning of newsgroups.  The function `gnus-subscribe-alphabetically'
-inserts it in strict alphabetic order.  The function
-`gnus-subscribe-hierarchically' inserts it in hierarchical newsgroup
-order.  The function `gnus-subscribe-interactively' asks for your decision.")
+(defvar gnus-subscribe-newsgroup-method 'gnus-subscribe-zombies
+  "Function 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.")
 
 ;; Suggested by a bug report by Hallvard B Furuseth
 ;; <h.b.furuseth@usit.uio.no>. 
@@ -582,6 +644,23 @@ options -n no.all alt.all
 Gnus will the subscribe all new newsgroups in these hierarchies with
 the subscription method in this variable.")
 
+(defvar gnus-subscribe-hierarchical-interactive nil
+  "If non-nil, Gnus will offer to subscribe hierarchically.
+When a new hierarchy appears, Gnus will ask the user:
+
+'alt.binaries': Do you want to subscribe to this hierarchy? ([d]ys):
+
+If the user pressed `d', Gnus will descend the hierarchy, `y' will
+subscribe to all newsgroups in the hierarchy and `s' will skip this
+hierarchy in its entirety.")
+
+(defvar gnus-group-sort-function 'gnus-group-sort-by-alphabet
+  "Function used for sorting the group buffer.
+This function will be called with group info entries as the arguments
+for the groups to be sorted.  Pre-made functions include
+`gnus-sort-by-alphabet', `gnus-sort-by-unread' and
+`gnus-sort-by-level'")
+
 ;; Mark variables suggested by Thomas Michanek
 ;; <Thomas.Michanek@telelogic.se>. 
 (defvar gnus-unread-mark ? 
@@ -606,8 +685,8 @@ the subscription method in this variable.")
   "Mark used for articles that are caught up.")
 (defvar gnus-replied-mark ?R
   "Mark used for articles that have been replied to.")
-(defvar gnus-process-mark ?#
-  "Mark used for marking articles as processable.")
+(defvar gnus-process-mark ?# 
+  "Process mark.")
 (defvar gnus-ancient-mark ?A
   "Mark used for ancient articles.")
 (defvar gnus-canceled-mark ?G
@@ -625,153 +704,10 @@ the subscription method in this variable.")
 If `not-confirm', pseudos will be viewed automatically, and the user
 will not be asked to confirm the command.")
 
-(defvar gnus-group-mode-hook nil
-  "A hook for Gnus group mode.")
-
-(defvar gnus-summary-mode-hook nil
-  "A hook for Gnus summary mode.")
-
-(defvar gnus-article-mode-hook nil
-  "A hook for Gnus article mode.")
-
-(defvar gnus-kill-file-mode-hook nil
-  "A hook for Gnus KILL File mode.")
-
-(defvar gnus-open-server-hook nil
-  "A hook called just before opening connection to news server.")
-
-(defvar gnus-startup-hook nil
-  "A hook called at startup time.
-This hook is called after Gnus is connected to the NNTP server. So, it
-is possible to change the behavior of Gnus according to the selected
-NNTP server.")
-
-(defvar gnus-group-prepare-function 'gnus-group-prepare-flat
-  "A function that is called to set up the group buffer.
-The function is called with three arguments: The first is a number;
-all group with a level less or equal to that number should be listed,
-if the second is non-nil, empty groups should also be displayed. If
-the third is non-nil, it is a number. No groups with a level lower
-than this number should be displayed.")
-
-(defvar gnus-group-prepare-hook nil
-  "A hook called after the newsgroup list is created in the group buffer.
-If you want to modify the group buffer, you can use this hook.")
-
-(defvar gnus-summary-prepare-hook nil
-  "A hook called after summary list is created in the summary buffer.
-If you want to modify the summary buffer, you can use this hook.")
-
-(defvar gnus-article-prepare-hook nil
-  "A hook called after an article is prepared in the article buffer.
-If you want to run a special decoding program like nkf, use this hook.")
-
-(defvar gnus-article-display-hook nil
-  "A hook called after the article is displayed in the article buffer.
-The hook is designed to change the contents of the article
-buffer. Typical functions that this hook may contain are
-`gnus-article-hide-headers' (hide selected headers),
-`gnus-article-hide-signature' (hide signature) and
-`gnus-article-treat-overstrike' (turn \"^H_\" into bold characters).")
-(add-hook 'gnus-article-display-hook 'gnus-article-hide-headers-if-wanted)
-(add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
-
-(defvar gnus-select-group-hook nil
-  "A hook called when a newsgroup is selected.
-
-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)
-                    (header-set-subject
-                     header
-                     (gnus-simplify-subject
-                      (header-subject header) 're-only)))
-                 gnus-newsgroup-headers))))
-")
-
-(defvar gnus-select-article-hook
-  '(gnus-summary-show-thread)
-  "A hook called when an article is selected.
-The default hook shows conversation thread subtrees of the selected
-article automatically using `gnus-summary-show-thread'.")
-
-(defvar gnus-apply-kill-hook '(gnus-apply-kill-file)
-  "A hook called when a newsgroup is selected and summary list is prepared.
-This hook is intended to apply a kill file to the selected newsgroup.
-The function `gnus-apply-kill-file' is called by default.
-
-Since a general kill file is too heavy to use only for a few
-newsgroups, I recommend you to use a lighter hook function. For
-example, if you'd like to apply a kill file to articles which contains
-a string `rmgroup' in subject in newsgroup `control', you can use the
-following hook:
-
-\(setq gnus-apply-kill-hook
-      (list
-       (lambda ()
-         (cond ((string-match \"control\" gnus-newsgroup-name)
-                (gnus-kill \"Subject\" \"rmgroup\")
-                (gnus-expunge \"X\"))))))")
-
-(defvar gnus-visual-mark-article-hook 
-  (list 'gnus-visual-highlight-selected-summary)
-  "Hook run after selecting an article in the summary buffer.
-It is meant to be used for highlighting the article in some way. It is
-not run if `gnus-visual' is nil.")
-
-(defvar gnus-prepare-article-hook (list (function gnus-inews-insert-signature))
-  "A hook called after preparing body, but before preparing header headers.
-The default hook (`gnus-inews-insert-signature') inserts a signature
-file specified by the variable `gnus-signature-file'.")
-
-(defvar gnus-inews-article-hook (list (function gnus-inews-do-fcc))
-  "A hook called before finally posting an article.
-The default hook (`gnus-inews-do-fcc') does FCC processing (save article
-to a file).")
-
-(defvar gnus-inews-article-header-hook nil
-  "A hook called after inserting the headers in an article to be posted.
-The hook is called from the *post-news* buffer, narrowed to the
-headers.")
-
-(defvar gnus-exit-group-hook nil
-  "A hook called when exiting (not quitting) summary mode.
-If your machine is so slow that exiting from summary mode takes very
-long time, set the variable `gnus-use-cross-reference' to nil. This
-inhibits marking articles as read using cross-reference information.")
-
-(defvar gnus-suspend-gnus-hook nil
-  "A hook called when suspending (not exiting) Gnus.")
-
-(defvar gnus-exit-gnus-hook (list 'nntp-request-close)
-  "A hook called when exiting Gnus.")
-
-(defvar gnus-save-newsrc-hook nil
-  "A hook called when saving the newsrc file.
-This hook is called before saving the `.newsrc' file.")
-
-(defvar gnus-auto-expirable-newsgroups nil
-  "All newsgroups that match this regexp will have all read articles automatically marked as expirable.")
-
-(defvar gnus-subscribe-hierarchical-interactive nil
-  "If non-nil, Gnus will offer to subscribe hierarchically.
-When a new hierarchy appears, Gnus will ask the user:
-
-'alt.binaries': Do you want to subscribe to this hierarchy? ([d]ys):
-
-If the user pressed `d', Gnus will descend the hierarchy, `y' will
-subscribe to all newsgroups in the hierarchy and `s' will skip this
-hierarchy in its entirety.")
-
 (defvar gnus-group-line-format "%M%S%5y: %(%g%)\n"
   "Format of groups lines.
 It works along the same lines as a normal formatting string,
-with some simple extrensions.
+with some simple extensions.
 
 %M    Only marked articles (character, \"*\" or \" \")
 %S    Whether the group is subscribed (character, \"U\", \"K\", \"Z\" or \" \")
@@ -792,11 +728,11 @@ with some simple extrensions.
 %n    Select from where (string)
 %z    A string that look like `<%s:%n>' if a foreign select method is used
 %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,
+      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 summary just like information from any other
-      summary specifier.
+      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.
@@ -838,7 +774,7 @@ with some simple extensions.
 %i   Article score (number)
 %z   Article zcore (character)
 %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,
+     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 summary just like information from any other
@@ -850,7 +786,7 @@ 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
+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,
 you might not be arrested, but your summary buffer will look strange,
 which is bad enough.
@@ -860,7 +796,7 @@ possible.
 
 This restriction may disappear in later versions of Gnus.")
 
-(defconst gnus-summary-dummy-line-format "*   :                          : %S\n"
+(defvar gnus-summary-dummy-line-format "*   :                          : %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.
@@ -873,114 +809,60 @@ with some simple extensions.
 (defvar gnus-article-mode-line-format "(ding) %G/%A %S"
   "The format specification for the article mode line.")
 
-(defconst gnus-group-mode-line-format "(ding) List of groups   {%M:%S}"
+(defvar gnus-group-mode-line-format "(ding) List of groups   {%M:%S}  "
   "The format specification for the group mode line.")
 
-
-\f
-;; Site dependent variables. You have to define these variables in
-;;  site-init.el, default.el or your .emacs.
-
-(defvar gnus-local-timezone nil
-  "Local time zone.
-This value is used only if `current-time-zone' does not work in your Emacs.
-It specifies the GMT offset, i.e. a decimal integer
-of the form +-HHMM giving the hours and minutes ahead of (i.e. east of) GMT.
-For example, +0900 should be used in Japan, since it is 9 hours ahead of GMT.
-
-For backwards compatibility, it may also be a string like \"JST\",
-but strings are obsolescent: you should use numeric offsets instead.")
-
-(defvar 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
-no need to set this variable.")
-
-(defvar gnus-local-organization nil
-  "String with a description of what organization (if any) the user belongs to.
-The ORGANIZATION environment variable is used instead if it is defined.
-If this variable contains a function, this function will be called
-with the current newsgroup name as the argument. The function should
-return a string.
-In any case, if the string (either in the variable, in the environment
-variable, or returned by the function) is a file name, the contents of
-this file will be used as the organization.")
-
-(defvar gnus-use-generic-from nil
-  "If nil, the full host name will be the system name prepended to the domain name.
-If this is a string, the full host name will be this string.
-If this is non-nil, non-string, the domain name will be used as the
-full host name.")
-
-(defvar gnus-use-generic-path nil
-  "If nil, use the NNTP server name in the Path header.
-If stringp, use this; if non-nil, use no host name (user name only).")
-
 (defvar gnus-valid-select-methods
-  '(("nntp" post address) ("nnspool" post) ("nnvirtual" none virtual) 
+  '(("nntp" post address prompt-address)
+    ("nnspool" post) ("nnvirtual" none virtual prompt-address) 
     ("nnmbox" mail respool) ("nnml" mail respool)
-    ("nnmh" mail respool) ("nndir" none) ("nndigest" none)
-    ("nndoc" none) ("nnbabyl" mail respool)
-    ("nnkiboze" none virtual))
-  "A list of valid select methods.
-Each element in this list should be a list. The first element of these
-lists should be a string with the name of the select method. The
-other elements may be be the category of this method (ie. `post',
-`mail', `none' or whatever) or other properties that this method has
- (like being respoolable). 
+    ("nnmh" mail respool) ("nndir" none prompt-address) ("nndigest" none)
+    ("nndoc" none prompt-address) ("nnbabyl" mail respool)
+    ("nnkiboze" none virtual) ("nnfolder" mail respool))
+  "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 be the category of
+this method (ie. `post', `mail', `none' or whatever) or other
+properties that this method has (like being respoolable).
 If you implement a new select method, all you should have to change is
 this variable. I think.")
 
 (defvar gnus-updated-mode-lines '(group article summary)
-  "This variable is a list of buffers that should keep their mode lines updated.
+  "List of buffers that should update their mode lines.
 The list may contain the symbols `group', `article' and `summary'. If
 the corresponding symbol is present, Gnus will keep that mode line
 updated with information that may be pertinent. 
 If this variable is nil, screen refresh may be quicker.")
 
+;; Added by Keinonen Kari <kk85613@cs.tut.fi>.
+(defvar gnus-mode-non-string-length 21
+  "Max length of mode-line non-string contents buffer contents.")
+
 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defvar gnus-mouse-face 'highlight
   "Face used for mouse highlighting in Gnus.
 No mouse highlights will be done if `gnus-visual' is nil.")
 
-(defvar gnus-visual-summary-update-hook 
-  (list 'gnus-visual-summary-highlight-line)
-  "A hook called when a summary line is changed.
-The hook will not be called if `gnus-visual' is nil.
-
-Point will be at the beginning of the line, and the following free
-variables can be used for convenience:
-
-score:   (gnus-summary-article-score)
-default: gnus-summary-default-score
-below:   gnus-summary-mark-below
-
-The default hook `gnus-visual-summary-highlight-line' will highlight the line
-according to the `gnus-visual-summary-highlight' variable.")
-
 (defvar gnus-summary-mark-below nil
-  "Score below which articles automatically become marked.
-This variable is local to each summary buffer and usually set in the
+  "Mark all articles with a score below this variable as read.
+This variable is local to each summary buffer and usually set by the
 score file.")  
 
 (defvar gnus-thread-sort-functions '(gnus-thread-sort-by-number)
-  "List of functions used for thread roots in the summary buffer.
+  "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,
-list the function you want to act as the primary sort key last.
+the primary sort function should be the last.
 
-Functions you can use are:
-- 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
-- gnus-thread-sort-by-total-score (see `gnus-thread-score-function').
+Ready-mady 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').
 
-The two later only works on articles that have already been scored prior
-to entering the newsgroup.")
+The latter two only work on threads that have been scored prior to
+entering the newsgroup.")
 
 (defvar gnus-thread-score-function '+
   "Function used for calculating the total score of a thread.
@@ -992,42 +874,237 @@ Some functions you can use are `+', `max', or `min'.")
 
 (defvar gnus-score-find-score-files-function 'gnus-score-find-bnews
   "Function used to find SCORE files.
-The value should be a function that takes a group name as an argument,
-and return a list of SCORE files that applies to that group.
+The function will be called with the group name as the argument, and
+should return a list of score files to apply to that group.  The score
+files do not actually have to exist.
 
 Predefined values are:
 
-gnus-score-find-single: Only apply the groups own SCORE file.
+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 definition of the individual functions for more information.")
+See the documentation to these functions for more information.")
 
 (defvar gnus-options-subscribe nil
-  "All new groups matching this regexp will be subscribed.
-Note that this variable deals only with new newsgroups. This variable
+  "All new groups matching this regexp will be subscribed unconditionally.
+Note that this variable deals only with new newsgroups.  This variable
 does not affect old newsgroups.")
 
 (defvar gnus-options-not-subscribe nil
   "All new groups matching this regexp will be ignored.
-Note that this variable deals only with new newsgroups. This variable
+Note that this variable deals only with new newsgroups.  This variable
 does not affect old (already subscribed) newsgroups.")
 
+(defvar gnus-auto-expirable-newsgroups nil
+  "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.")
+
+
+;; Hooks.
+
+(defvar gnus-group-mode-hook nil
+  "A hook for Gnus group mode.")
+
+(defvar gnus-summary-mode-hook nil
+  "A hook for Gnus summary mode.")
+
+(defvar gnus-article-mode-hook nil
+  "A hook for Gnus article mode.")
+
+(defvar gnus-kill-file-mode-hook nil
+  "A hook for Gnus kill file mode.")
+
+(defvar gnus-open-server-hook nil
+  "A hook called just before opening connection to the news server.")
+
+(defvar gnus-startup-hook nil
+  "A hook called at startup.
+This hook is called after Gnus is connected to the NNTP server.")
+
+(defvar gnus-get-new-news-hook nil
+  "A hook run just before Gnus checks for new news.")
+
+(defvar gnus-group-prepare-function 'gnus-group-prepare-flat
+  "A function that is called to generate the group buffer.
+The function is called with three arguments: The first is a number;
+all group with a level less or equal to that number should be listed,
+if the second is non-nil, empty groups should also be displayed. If
+the third is non-nil, it is a number. No groups with a level lower
+than this number should be displayed.
+
+The only current function implemented is `gnus-group-prepare-flat'.")
+
+(defvar gnus-group-prepare-hook nil
+  "A hook called after the group buffer has been generated.
+If you want to modify the group buffer, you can use this hook.")
+
+(defvar gnus-summary-prepare-hook nil
+  "A hook called after the summary buffer has been generated.
+If you want to modify the summary buffer, you can use this hook.")
+
+(defvar 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.")
+
+(defvar gnus-article-display-hook nil
+  "A hook called after the article is displayed in the article buffer.
+The hook is designed to change the contents of the article
+buffer. Typical functions that this hook may contain are
+`gnus-article-hide-headers' (hide selected headers),
+`gnus-article-hide-signature' (hide signature) and
+`gnus-article-treat-overstrike' (turn \"^H_\" into bold characters).")
+(add-hook 'gnus-article-display-hook 'gnus-article-hide-headers-if-wanted)
+(add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
+
+(defvar gnus-select-group-hook nil
+  "A hook called when a newsgroup is selected.
+
+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)
+                    (header-set-subject
+                     header
+                     (gnus-simplify-subject
+                      (header-subject header) 're-only)))
+                 gnus-newsgroup-headers))))")
+
+(defvar gnus-select-article-hook
+  '(gnus-summary-show-thread)
+  "A hook called when an article is selected.
+The default hook shows conversation thread subtrees of the selected
+article automatically using `gnus-summary-show-thread'.")
+
+(defvar gnus-apply-kill-hook '(gnus-apply-kill-file)
+  "A hook called to apply kill files to a group.
+This hook is intended to apply a kill file to the selected newsgroup.
+The function `gnus-apply-kill-file' is called by default.
+
+Since a general kill file is too heavy to use only for a few
+newsgroups, I recommend you to use a lighter hook function. For
+example, if you'd like to apply a kill file to articles which contains
+a string `rmgroup' in subject in newsgroup `control', you can use the
+following hook:
+
+\(setq gnus-apply-kill-hook
+      (list
+       (lambda ()
+         (cond ((string-match \"control\" gnus-newsgroup-name)
+                (gnus-kill \"Subject\" \"rmgroup\")
+                (gnus-expunge \"X\"))))))")
+
+(defvar gnus-visual-mark-article-hook 
+  (list 'gnus-visual-highlight-selected-summary)
+  "Hook run after selecting an article in the summary buffer.
+It is meant to be used for highlighting the article in some way.  It
+is not run if `gnus-visual' is nil.")
+
+(defvar gnus-prepare-article-hook (list 'gnus-inews-insert-signature)
+  "A hook called after preparing body, but before preparing header headers.
+The default hook (`gnus-inews-insert-signature') inserts a signature
+file specified by the variable `gnus-signature-file'.")
+
+(defvar gnus-inews-article-hook (list 'gnus-inews-do-fcc)
+  "A hook called before finally posting an article.
+The default hook (`gnus-inews-do-fcc') does FCC processing (ie. saves
+the article to a file).")
+
+(defvar gnus-inews-article-header-hook nil
+  "A hook called after inserting the headers in an article to be posted.
+The hook is called from the *post-news* buffer, narrowed to the
+headers.")
+
+(defvar gnus-exit-group-hook nil
+  "A hook called when exiting (not quitting) summary mode.")
+
+(defvar gnus-suspend-gnus-hook nil
+  "A hook called when suspending (not exiting) Gnus.")
+
+(defvar gnus-exit-gnus-hook nil
+  "A hook called when exiting Gnus.")
+
+(defvar gnus-save-newsrc-hook nil
+  "A hook called when saving the newsrc file.")
+
+(defvar gnus-visual-summary-update-hook 
+  (list 'gnus-visual-summary-highlight-line)
+  "A hook called when a summary line is changed.
+The hook will not be called if `gnus-visual' is nil.
+
+The default function `gnus-visual-summary-highlight-line' will
+highlight the line according to the `gnus-visual-summary-highlight'
+variable.")
+
+(defvar gnus-mark-article-hook (list 'gnus-summary-mark-unread-as-read)
+  "A hook called when an article is selected for the first time.
+The hook is intended to mark an article as read (or unread)
+automatically when it is selected.")
+
+;; Site dependent variables. These variables should be defined in
+;; paths.el.
+
+(defvar gnus-default-nntp-server nil
+  "Specify a default NNTP server.
+This variable should be defined in paths.el, and should never be set
+by the user.
+If you want to change servers, you should use `gnus-select-method'.
+See the documentation to that variable.")
+
+(defconst gnus-backup-default-subscribed-newsgroups 
+  '("news.announce.newusers" "news.groups.questions" "gnu.emacs.gnus")
+  "Default default new newsgroups the first time Gnus is run.
+Should be set in paths.el, and shouldn't be touched by the user.")
+
+(defvar 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
+no need to set this variable.")
+
+(defvar gnus-local-organization nil
+  "String with a description of what organization (if any) the user belongs to.
+The ORGANIZATION environment variable is used instead if it is defined.
+If this variable contains a function, this function will be called
+with the current newsgroup name as the argument. The function should
+return a string.
+In any case, if the string (either in the variable, in the environment
+variable, or returned by the function) is a file name, the contents of
+this file will be used as the organization.")
+
+(defvar gnus-use-generic-from nil
+  "If nil, the full host name will be the system name prepended to the domain name.
+If this is a string, the full host name will be this string.
+If this is non-nil, non-string, the domain name will be used as the
+full host name.")
+
+(defvar gnus-use-generic-path nil
+  "If nil, use the NNTP server name in the Path header.
+If stringp, use this; if non-nil, use no host name (user name only).")
+
 \f
 ;; Internal variables
 
 ;; Avoid highlighting in kill files.
 (defvar gnus-summary-inhibit-highlight nil)
+(defvar gnus-newsgroup-selected-overlay nil)
 
+(defvar gnus-article-mode-map nil)
 (defvar caesar-translate-table nil)
-
 (defvar gnus-dribble-buffer nil)
 (defvar gnus-headers-retrieved-by nil)
-
 (defvar gnus-article-reply nil)
+(defvar gnus-override-method nil)
 (defvar gnus-article-check-size nil)
-
 (defvar gnus-score-file-list nil)
+(defvar gnus-internal-global-score-files nil)
+(defvar gnus-current-score-file nil)
+
 (defvar gnus-score-alist nil
   "Alist containing score information.
 The keys can be symbols or strings.  The following symbols are defined. 
@@ -1045,24 +1122,15 @@ substring matching, SCORE is the score to add and DATE is the date
 of the last succesful match.")
 
 (defvar gnus-score-cache nil)
-;; Alist containing the content of all loaded SCORE files.
-(defvar gnus-scores-lists nil)
 (defvar gnus-scores-articles nil)
 (defvar gnus-header-index nil)
 (defvar gnus-score-index nil)
 
 (defvar gnus-newsgroup-dependencies nil)
-
 (defconst gnus-group-edit-buffer "*Gnus edit newsgroup*")
-
-(defvar gnus-default-subscribe-level 2
-  "Default subscription level.")
-
-(defvar gnus-default-unsubscribe-level 6
-  "Default unsubscription level.")
-
-(defvar gnus-default-kill-level 9
-  "Default kill level.")
+(defvar gnus-default-subscribe-level 2)
+(defvar gnus-default-unsubscribe-level 6)
+(defvar gnus-default-kill-level 9)
 
 (defconst gnus-group-line-format-alist
   (list (list ?M 'marked ?c)
@@ -1135,14 +1203,13 @@ variable (string, integer, character, etc).")
 (defconst gnus-maintainer "Lars Magne Ingebrigtsen <larsi@ifi.uio.no>"
   "The mail address of the Gnus maintainer.")
 
-(defconst gnus-version "(ding) Gnus v0.30"
+(defconst gnus-version "(ding) Gnus v0.40"
   "Version number for this version of Gnus.")
 
 (defvar gnus-info-nodes
-  '((gnus-group-mode           "(gnus)Group Commands")
-    (gnus-summary-mode         "(gnus)Summary Commands")
-    (gnus-article-mode         "(gnus)Article Commands")
-    (gnus-kill-file-mode       "(gnus)Kill File"))
+  '((gnus-group-mode           "(gnus)The Group Buffer")
+    (gnus-summary-mode         "(gnus)The Summary Buffer")
+    (gnus-article-mode         "(gnus)The Article Buffer"))
   "Assoc list of major modes and related Info nodes.")
 
 (defvar gnus-documentation-group-file "~/dgnus/lisp/doc.txt"
@@ -1153,7 +1220,7 @@ variable (string, integer, character, etc).")
 (defvar gnus-article-buffer "*Article*")
 
 (defvar gnus-buffer-list nil
-  "Gnus buffers that should be killed when exiting.")
+  "Gnus buffers that should be killed on exit.")
 
 (defvar gnus-variable-list
   '(gnus-newsrc-options 
@@ -1231,10 +1298,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (defvar gnus-newsgroup-last-mail nil)
 (defvar gnus-newsgroup-last-folder nil)
 (defvar gnus-newsgroup-last-file nil)
-(defvar gnus-newsgroup-auto-expire nil
-  "If non-nil, all read articles will be marked as expirable.")
-
-(defvar gnus-newsgroup-selected-overlay nil)
+(defvar gnus-newsgroup-auto-expire nil)
 
 (defvar gnus-newsgroup-unreads nil
   "List of unread articles in the current newsgroup.")
@@ -1278,18 +1342,15 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (defvar gnus-current-article nil)
 (defvar gnus-article-current nil)
 (defvar gnus-current-headers nil)
-(defvar gnus-have-all-headers nil "Must be either T or NIL.")
+(defvar gnus-have-all-headers nil)
 (defvar gnus-last-article nil)
+(defvar gnus-newsgroup-history nil)
 (defvar gnus-current-kill-article nil)
-(defvar gnus-newsgroup-dormant-subjects nil)
-(defvar gnus-newsgroup-expunged-buffer nil)
 
 ;; Save window configuration.
 (defvar gnus-winconf-kill-file nil)
-
-(defconst gnus-group-mode-map nil)
-(defvar gnus-article-mode-map nil)
-(defvar gnus-kill-file-mode-map nil)
+(defvar gnus-winconf-edit-group nil)
+(defvar gnus-winconf-edit-score nil)
 
 ;; Format specs
 (defvar gnus-summary-line-format-spec nil)
@@ -1298,11 +1359,11 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (defvar gnus-summary-mode-line-format-spec nil)
 (defvar gnus-article-mode-line-format-spec nil)
 (defvar gnus-group-mode-line-format-spec nil)
+(defvar gnus-summary-mark-positions nil)
+
 (defvar gnus-summary-expunge-below nil)
 (defvar gnus-reffed-article-number nil)
 
-(defvar gnus-summary-mark-positions nil)
-
 (defvar rmail-default-file (expand-file-name "~/XMBOX"))
 (defvar rmail-default-rmail-file (expand-file-name "~/XNEWS"))
 
@@ -1316,35 +1377,19 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
     gnus-newsgroup-replied gnus-newsgroup-expirable
     gnus-newsgroup-processable gnus-newsgroup-killed
     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
-    gnus-newsgroup-dormant-subjects gnus-newsgroup-expunged-buffer
     gnus-newsgroup-headers gnus-newsgroup-headers-hashtb-by-number
     gnus-current-article gnus-current-headers gnus-have-all-headers
     gnus-last-article gnus-article-internal-prepare-hook
-    gnus-newsgroup-selected-overlay gnus-newsgroup-dependencies
+    gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
     gnus-newsgroup-scored gnus-newsgroup-kill-headers
-    gnus-score-alist gnus-summary-expunge-below 
-    gnus-summary-mark-below gnus-newsgroup-ancient)
+    gnus-score-alist gnus-current-score-file gnus-summary-expunge-below 
+    (gnus-summary-mark-below . gnus-summary-default-score)
+    gnus-newsgroup-history gnus-newsgroup-ancient)
   "Variables that are buffer-local to the summary buffers.")
 
-(defvar gnus-mark-article-hook
-  (list
-   (lambda ()
-     (or (memq gnus-current-article gnus-newsgroup-marked)
-        (memq gnus-current-article gnus-newsgroup-dormant)
-        (memq gnus-current-article gnus-newsgroup-expirable)
-        (gnus-summary-mark-as-read gnus-current-article gnus-read-mark))))
-  "A hook called when an article is selected at the first time.
-The hook is intended to mark an article as read (or unread)
-automatically when it is selected.
-
-If you'd like to tick articles instead, use the following hook:
-
-\(setq gnus-mark-article-hook
-      (list
-        (lambda ()
-         (gnus-summary-tick-article gnus-current-article))))")
+;;; End of variables.
 
-;; Define some autoload functions Gnus may use.
+;; Define some autoload functions Gnus might use.
 (eval-and-compile
   (autoload 'metamail-buffer "metamail")
   (autoload 'Info-goto-node "info")
@@ -1354,10 +1399,10 @@ If you'd like to tick articles instead, use the following hook:
   (autoload 'timezone-make-sortable-date "timezone")
   (autoload 'timezone-make-time-string "timezone")
   
-  (autoload 'rmail-output "rmailout"
-    "Append this message to Unix mail file named FILE-NAME." t)
+  (autoload 'rmail-output "rmailout")
   (autoload 'mail-position-on-field "sendmail")
   (autoload 'mail-setup "sendmail")
+  (autoload 'news-mail-other-window "rnewspost")
 
   (autoload 'gnus-mail-reply-using-mhe "gnus-mh")
   (autoload 'gnus-mail-forward-using-mhe "gnus-mh")
@@ -1372,7 +1417,6 @@ If you'd like to tick articles instead, use the following hook:
   (autoload 'gnus-visual-highlight-selected-summary "gnus-visual")
   (autoload 'gnus-visual-summary-highlight-line "gnus-visual")
 
-  (autoload 'gnus-uu-decode-map "gnus-uu" nil nil 'keymap)
   (autoload 'gnus-uu-mark-by-regexp "gnus-uu")
   (autoload 'gnus-uu-mark-region "gnus-uu")
   (autoload 'gnus-uu-mark-thread "gnus-uu")
@@ -1396,6 +1440,8 @@ If you'd like to tick articles instead, use the following hook:
   (autoload 'gnus-uu-decode-binhex-view "gnus-uu")
 
   (autoload 'pp "pp")
+  (autoload 'pp-to-string "pp")
+  (autoload 'mail-extract-address-components "mail-extr")
   )
 
 (put 'gnus-group-mode 'mode-class 'special)
@@ -1458,15 +1504,16 @@ Optional argument HASHSIZE specifies the table size."
 
 (defun gnus-extract-address-components (from)
   (let (name address)
-    (if (string-match "([^)]+)" from)
-       (setq name (substring from (1+ (match-beginning 0)) 
-                             (1- (match-end 0)))))
-    ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
     (if (string-match "\\b[^@ \t<>]+[!@][^@ \t<>]+\\b" from)
        (setq address (substring from (match-beginning 0) (match-end 0))))
-    (if (and (not name) address)
-       (if (string-match (concat "<" (regexp-quote address) ">") from)
-           (setq name (substring from 0 (1- (match-beginning 0))))))
+    (and address
+        (string-match (concat "<" (regexp-quote address) ">") from)
+        (setq name (substring from 0 (1- (match-beginning 0)))))
+    (or name
+       (and (string-match "(.+)" from)
+            (setq name (substring from (1+ (match-beginning 0)) 
+                                  (1- (match-end 0))))))
+    ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
     (list (or name from) (or address from))))
 
 (defun gnus-fetch-field (field)
@@ -1530,7 +1577,7 @@ Optional argument HASHSIZE specifies the table size."
       (buffer-disable-undo (current-buffer))
       (erase-buffer)
       (gnus-summary-insert-line 
-       nil ["" "" "" "" "" "" 0 0 ""]  0 nil 128 t nil "" nil 1)
+       nil [0 "" "" "" "" "" 0 0 ""]  0 nil 128 t nil "" nil 1)
       (goto-char (point-min))
       (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
                                         (- (point) 2)))))
@@ -1585,7 +1632,7 @@ Optional argument HASHSIZE specifies the table size."
   (let ((max-width 0)
        spec flist fstring b newspec max-width elem beg)
     (save-excursion
-      (set-buffer (get-buffer-create "*gnus work*"))
+      (set-buffer (get-buffer-create " *gnus work*"))
       (buffer-disable-undo (current-buffer))
       (gnus-add-current-to-buffer-list)
       (erase-buffer)
@@ -1882,7 +1929,7 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
   (setq gnus-buffer-list (cons (current-buffer) gnus-buffer-list)))
 
 ;; Functions accessing headers.
-;; Functions are more convenient than macros in some case.
+;; Functions are more convenient than macros in some cases.
 
 (defun gnus-header-number (header)
   "Return article number in HEADER."
@@ -1937,12 +1984,13 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
        gnus-newsgroup-headers nil
        gnus-score-cache nil
        gnus-newsgroup-headers-hashtb-by-number nil
+       gnus-newsgroup-name nil
+       gnus-internal-global-score-files nil
        gnus-current-select-method nil)
   ;; Kill the startup file.
   (and gnus-current-startup-file
        (get-file-buffer gnus-current-startup-file)
        (kill-buffer (get-file-buffer gnus-current-startup-file)))
-  (setq gnus-current-startup-file nil)
   (gnus-dribble-clear)
   ;; Kill global KILL file buffer.
   (if (get-file-buffer (gnus-newsgroup-kill-file nil))
@@ -2051,14 +2099,13 @@ or not."
              ;; It seems that some code in this function will set
              ;; buffer-read-only to nil. I have absolutely no idea
              ;; why. 
-             (setq buffer-read-only t))) ; !!! Why!?! 
-       ))))
+             (setq buffer-read-only t))))))) ; !!! Why!?! 
 
 (defun gnus-window-configuration-split (action)
   (switch-to-buffer gnus-group-buffer t)
   (delete-other-windows)
   (split-window-horizontally)
-  (cond ((or (eq action 'newsgroups) (eq action 'summary))
+  (cond ((or (eq action 'newsgoups) (eq action 'summary))
         (if (and (get-buffer gnus-summary-buffer)
                  (buffer-name gnus-summary-buffer))
             (switch-to-buffer-other-window gnus-summary-buffer)))
@@ -2136,7 +2183,8 @@ The source file has to be in the Emacs load path."
              (and (eq (car expr) 'defvar)
                   (stringp (nth 3 expr))
                   (not (equal (eval (nth 2 expr))
-                              (symbol-value (nth 1 expr))))
+                              (and (boundp (nth 1 expr))
+                                   (symbol-value (nth 1 expr)))))
                   (setq olist (cons (nth 1 expr) olist))))
            (kill-buffer (current-buffer)))
        (setq dirs (cdr dirs))))
@@ -2159,8 +2207,7 @@ If nothing is specified, use the variable gnus-overload-functions."
       (and (not (fboundp (car defs)))
           (car (cdr (cdr defs)))
           (load (car (cdr (cdr defs))) nil 'nomessage))
-      (fset (car defs) (car (cdr defs)))
-      )))
+      (fset (car defs) (car (cdr defs))))))
 
 (defun gnus-replace-chars-in-string (string from to)
   "Replace characters in STRING from FROM to TO."
@@ -2185,12 +2232,20 @@ If nothing is specified, use the variable gnus-overload-functions."
        (timezone-absolute-from-gregorian 
        (nth 1 d2) (nth 2 d2) (car d2)))))
 
+(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-file-newer-than (file date)
   (let ((fdate (nth 5 (file-attributes file))))
     (or (> (car fdate) (car date))
        (and (= (car fdate) (car date))
             (> (nth 1 fdate) (nth 1 date))))))
 
+;; Two silly functions to ensure that all `y-or-n-p' questions clear
+;; the echo area.
 (defun gnus-y-or-n-p (prompt)
   (prog1
       (y-or-n-p prompt)
@@ -2220,14 +2275,38 @@ If nothing is specified, use the variable gnus-overload-functions."
     (setq list (cdr list)))
   (car list))
 
+(defun gnus-copy-sequence (list)
+  "Do a complete, total copy of a list."
+  (mapcar (lambda (elem) (if (consp elem) 
+                            (if (consp (cdr elem))
+                                (gnus-copy-sequence elem)
+                              (cons (car elem) (cdr elem)))
+                          elem))
+         list))
+
 (defun gnus-set-difference (list1 list2)
   "Return a list of elements of LIST1 that do not appear in LIST2."
   (let ((list1 (copy-sequence list1)))
     (while list2
       (setq list1 (delq (car list2) list1))
       (setq list2 (cdr list2)))
-    list1
-    ))
+    list1))
+
+(defun gnus-sorted-complement (list1 list2)
+  "Return a list of elements of LIST1 that do not appear in LIST2.
+Both lists have to be sorted over <."
+  (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 out (cons (car list2) out))
+            (setq list2 (cdr list2)))))
+    (append (or list1 list2) out)))
 
 (defun gnus-intersection (list1 list2)      
   (let ((result nil))
@@ -2235,8 +2314,39 @@ If nothing is specified, use the variable gnus-overload-functions."
       (if (memq (car list2) list1)
          (setq result (cons (car list2) result)))
       (setq list2 (cdr list2)))
-    result
-    ))
+    result))
+
+(defun gnus-sorted-intersection (list1 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 list1 (cdr list1)))
+           (t
+            (setq list2 (cdr list2)))))
+    out))
+
+(defun gnus-set-sorted-intersection (list1 list2)
+  ;; LIST1 and LIST2 have to be sorted over <.
+  ;; This function modifies LIST1.
+  (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))
+          (setcdr prev (cdr list1))
+          (setq list1 (cdr list1)))
+         (t
+          (setcdr prev (cdr list1))
+          (setq 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.
@@ -2335,39 +2445,46 @@ Note: LIST has to be sorted over `<'."
 Note: LIST has to be sorted over `<'."
   ;; !!! This function shouldn't look like this, but I've got a headache.
   (gnus-compress-sequence 
-   (gnus-set-difference 
+   (gnus-sorted-complement
     (gnus-uncompress-sequence ranges) list)))
 
 (defun gnus-member-of-range (number ranges)
-  (let ((not-stop t))
-    (while (and ranges not-stop)
-      (if (and (>= number (car (car ranges)))
-              (<= number (cdr (car ranges))))
-         (setq not-stop nil))
-      (setq ranges (cdr ranges)))
-    (not not-stop)))
+  (if (not (listp (car ranges)))
+      (and (>= number (car ranges)) 
+          (<= number (cdr ranges)))
+    (let ((not-stop t))
+      (while (and ranges (>= number (car (car ranges))) not-stop)
+       (if (and (>= number (car (car ranges)))
+                (<= number (cdr (car ranges))))
+           (setq not-stop nil))
+       (setq ranges (cdr ranges)))
+      (not not-stop))))
 
 \f
 ;;;
 ;;; Gnus group mode
 ;;;
 
+(defvar gnus-group-mode-map nil)
+(defvar gnus-group-make-map nil)
+(defvar gnus-group-list-map nil)
+
 (if gnus-group-mode-map
     nil
   (setq gnus-group-mode-map (make-keymap))
   (suppress-keymap gnus-group-mode-map)
   (define-key gnus-group-mode-map " " 'gnus-group-read-group)
   (define-key gnus-group-mode-map "=" 'gnus-group-select-group)
+  (define-key gnus-group-mode-map "\r" 'gnus-group-select-group)
   (define-key gnus-group-mode-map "j" 'gnus-group-jump-to-group)
   (define-key gnus-group-mode-map "n" 'gnus-group-next-unread-group)
   (define-key gnus-group-mode-map "p" 'gnus-group-prev-unread-group)
-  (define-key gnus-group-mode-map [del] 'gnus-group-prev-unread-group)
+  (define-key gnus-group-mode-map "\177" 'gnus-group-prev-unread-group)
   (define-key gnus-group-mode-map "N" 'gnus-group-next-group)
   (define-key gnus-group-mode-map "P" 'gnus-group-prev-group)
   (define-key gnus-group-mode-map "\M-n" 'gnus-group-next-unread-group-same-level)
   (define-key gnus-group-mode-map "\M-p" 'gnus-group-prev-unread-group-same-level)
   (define-key gnus-group-mode-map "," 'gnus-group-best-unread-group)
-  (define-key gnus-group-mode-map "\r" 'gnus-group-select-group)
   (define-key gnus-group-mode-map "u" 'gnus-group-unsubscribe-current-group)
   (define-key gnus-group-mode-map "U" 'gnus-group-unsubscribe-group)
   (define-key gnus-group-mode-map "c" 'gnus-group-catchup-current)
@@ -2386,11 +2503,7 @@ Note: LIST has to be sorted over `<'."
   (define-key gnus-group-mode-map "\M-d" 'gnus-group-describe-all-groups)
   (define-key gnus-group-mode-map "\C-c\C-a" 'gnus-group-apropos)
   (define-key gnus-group-mode-map "\C-c\M-C-a" 'gnus-group-description-apropos)
-  (define-key gnus-group-mode-map "D" 'gnus-group-make-doc-group)
-  (define-key gnus-group-mode-map "d" 'gnus-group-make-directory-group)
   (define-key gnus-group-mode-map "a" 'gnus-group-post-news)
-  (define-key gnus-group-mode-map "\M-a" 'gnus-group-add-group)
-  (define-key gnus-group-mode-map "\M-e" 'gnus-group-edit-group)
   (define-key gnus-group-mode-map "\ek" 'gnus-group-edit-local-kill)
   (define-key gnus-group-mode-map "\eK" 'gnus-group-edit-global-kill)
   (define-key gnus-group-mode-map "\C-k" 'gnus-group-kill-group)
@@ -2399,8 +2512,6 @@ Note: LIST has to be sorted over `<'."
   (define-key gnus-group-mode-map "\M-z" 'gnus-group-kill-all-zombies)
   (define-key gnus-group-mode-map "\C-x\C-t" 'gnus-group-transpose-groups)
   (define-key gnus-group-mode-map "\C-c\C-l" 'gnus-group-list-killed)
-  (define-key gnus-group-mode-map "\C-c\C-k" 'gnus-group-list-killed)
-  (define-key gnus-group-mode-map "\C-c\C-z" 'gnus-group-list-zombies)
   (define-key gnus-group-mode-map "\C-c\C-x" 'gnus-group-expire-articles)
   (define-key gnus-group-mode-map "\C-c\M-\C-x" 'gnus-group-expire-all-groups)
   (define-key gnus-group-mode-map "V" 'gnus-version)
@@ -2410,65 +2521,38 @@ Note: LIST has to be sorted over `<'."
   (define-key gnus-group-mode-map "Z" 'gnus-group-clear-dribble)
   (define-key gnus-group-mode-map "q" 'gnus-group-exit)
   (define-key gnus-group-mode-map "Q" 'gnus-group-quit)
+  (define-key gnus-group-mode-map "\M-f" 'gnus-group-fetch-faq)
   (define-key gnus-group-mode-map "?" 'gnus-group-describe-briefly)
   (define-key gnus-group-mode-map "\C-c\C-i" 'gnus-info-find-node)
-  (define-key gnus-group-mode-map [mouse-2] 'gnus-mouse-pick-group))
+  (define-key gnus-group-mode-map "\M-e" 'gnus-group-edit-group)
+  (define-key gnus-group-mode-map [mouse-2] 'gnus-mouse-pick-group)
+
+  (define-prefix-command 'gnus-group-make-map)
+  (define-key gnus-group-mode-map "M" 'gnus-group-make-map)
+  (define-key gnus-group-make-map "d" 'gnus-group-make-directory-group)
+  (define-key gnus-group-make-map "h" 'gnus-group-make-help-group)
+  (define-key gnus-group-make-map "k" 'gnus-group-make-kiboze-group)
+  (define-key gnus-group-make-map "m" 'gnus-group-make-group)
+  (define-key gnus-group-make-map "e" 'gnus-group-edit-group)
+
+  (define-prefix-command 'gnus-group-list-map)
+  (define-key gnus-group-mode-map "G" 'gnus-group-list-map)
+  (define-key gnus-group-list-map "k" 'gnus-group-list-killed)
+  (define-key gnus-group-list-map "z" 'gnus-group-list-zombies)
+  (define-key gnus-group-list-map "s" 'gnus-group-list-groups)
+  (define-key gnus-group-list-map "u" 'gnus-group-list-all-groups)
+  (define-key gnus-group-list-map "a" 'gnus-group-apropos)
+  (define-key gnus-group-list-map "d" 'gnus-group-description-apropos)
+  (define-key gnus-group-list-map "m" 'gnus-group-list-matching)
+  (define-key gnus-group-list-map "M" 'gnus-group-list-all-matching)
+  )
 
 (defun gnus-group-mode ()
   "Major mode for reading news.
 All normal editing commands are switched off.
 The following commands are available:
 
-\\<gnus-group-mode-map>
-\\[gnus-group-read-group]\t Choose the current group
-\\[gnus-group-select-group]\t Select the current group without selecting the first article
-\\[gnus-group-jump-to-group]\t Go to some group
-\\[gnus-group-next-unread-group]\t Go to the next unread group
-\\[gnus-group-prev-unread-group]\t Go to the previous unread group
-\\[gnus-group-next-group]\t Go to the next group
-\\[gnus-group-prev-group]\t Go to the previous group
-\\[gnus-group-next-unread-group-same-level]\t Go to the next unread group on the same level
-\\[gnus-group-prev-unread-group-same-level]\t Go to the previous unread group un the same level
-\\[gnus-group-unsubscribe-current-group]\t (Un)subscribe to the current group
-\\[gnus-group-unsubscribe-group]\t (Un)subscribe to some group
-\\[gnus-group-catchup-current]\t Mark all unread articles in the current group as read
-\\[gnus-group-catchup-current-all]\t Mark all alrticles in the current group as read
-\\[gnus-group-list-groups]\t List groups that have unread articles
-\\[gnus-group-list-all-groups]\t List all groups
-\\[gnus-group-mail]\t Compose a mail
-\\[gnus-group-get-new-news]\t Look for new news
-\\[gnus-group-get-new-news-this-group]\t Look for new news for the current group
-\\[gnus-group-restart]\t Restart Gnus
-\\[gnus-group-save-newsrc]\t Save the startup file(s)
-\\[gnus-group-browse-foreign-server]\t Browse a foreign (NNTP) server
-\\[gnus-group-check-bogus-groups]\t Check for and remove bogus newsgroups
-\\[gnus-find-new-newsgroups]\t Find new newsgroups
-\\[gnus-group-describe-group]\t Describe the current newsgroup
-\\[gnus-group-describe-all-groups]\t Describe all newsgroups
-\\[gnus-group-post-news]\t Post an article to some newsgroup
-\\[gnus-group-add-group]\t Add a newsgroup entry
-\\[gnus-group-edit-group]\t Edit a newsgroup entry
-\\[gnus-group-make-directory-group]\t Read a directory as a newsgroups
-\\[gnus-group-edit-local-kill]\t Edit a local kill file
-\\[gnus-group-edit-global-kill]\t Edit the global kill file
-\\[gnus-group-kill-group]\t Kill the current newsgroup
-\\[gnus-group-yank-group]\t Yank a previously killed newsgroup
-\\[gnus-group-kill-region]\t Kill all newsgroups between point and mark
-\\[gnus-group-kill-all-zombies]\t Kill all zombie newsgroups
-\\[gnus-group-transpose-groups]\t Transpose two newsgroups
-\\[gnus-group-list-killed]\t List all killed newsgroups
-\\[gnus-group-list-zombies]\t List all zombie newsgroups
-\\[gnus-group-expire-articles]\t Expire the expirable articles in the current newsgroup
-\\[gnus-group-expire-all-groups]\t Expire expirable articles in all newsgroups
-\\[gnus-version]\t Display the current Gnus version
-\\[gnus-group-set-current-level]\t Set the level of the current newsgroup
-\\[gnus-group-suspend]\t Suspend Gnus
-\\[gnus-group-clear-dribble]\t Clear the dribble buffer
-\\[gnus-group-exit]\t Stop reading news
-\\[gnus-group-quit]\t Stop reading news without saving the startup files
-\\[gnus-group-describe-briefly]\t Give a brief description of the current mode
-\\[gnus-info-find-node]\t Find the info pages for Gnus
-"
+\\{gnus-group-mode-map}"
   (interactive)
   (if gnus-visual (gnus-group-make-menu-bar))
   (kill-all-local-variables)
@@ -2528,6 +2612,7 @@ prompt the user for the name of an NNTP server to use."
        (if (and (not dont-connect) 
                 (not (gnus-server-opened gnus-select-method)))
            (gnus-group-quit)
+         (run-hooks 'gnus-startup-hook)
          ;; NNTP server is successfully open. 
          (gnus-update-format-specifications)
          (let ((buffer-read-only nil))
@@ -2536,7 +2621,6 @@ prompt the user for the name of an NNTP server to use."
                (progn
                  (gnus-group-startup-message)
                  (sit-for 0))))
-         (run-hooks 'gnus-startup-hook)
          (gnus-setup-news nil level)
          (and gnus-use-dribble-file (gnus-dribble-open))
          (or t (not gnus-novice-user)
@@ -2550,22 +2634,23 @@ prompt the user for the name of an NNTP server to use."
   (erase-buffer)
   (insert
    (format "
-%s
-       A newsreader 
-  for GNU Emacs
+    %s
+           A newsreader 
+      for GNU Emacs
 
-    Based on GNUS 
-         written by 
- Masanobu UMEDA
+        Based on GNUS 
+             written by 
    Masanobu UMEDA
 
-Lars Ingebrigtsen 
-  larsi@ifi.uio.no
+    Lars Magne 
+         Ingebrigtsen 
+      larsi@ifi.uio.no
 " 
           gnus-version))
   ;; And then hack it.
   ;; 18 is the longest line.
   (indent-rigidly (point-min) (point-max) 
-                 (/ (max (- (window-width) (or x 22)) 0) 2))
+                 (/ (max (- (window-width) (or x 28)) 0) 2))
   (goto-char (point-min))
   ;; +4 is fuzzy factor.
   (insert-char ?\n (/ (max (- (window-height) (or y 12)) 0) 2)))
@@ -2611,10 +2696,11 @@ If argument UNREAD is non-nil, groups with no unread articles are also listed."
       ;; Adjust cursor point.
       (gnus-group-position-cursor))))
 
-(defun gnus-group-prepare-flat (level &optional all lowest) 
+(defun gnus-group-prepare-flat (level &optional all 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 LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
+If LOWEST is non-nil, list all newsgroups of level LOWEST or higher.
+If REGEXP, only list groups matching REGEXP."
   (set-buffer gnus-group-buffer)
   (let ((buffer-read-only nil)
        (newsrc (cdr gnus-newsrc-assoc))
@@ -2629,6 +2715,8 @@ If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
                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 (car (cdr info))) level) 
               (>= clevel lowest)
               (or all            ; We list all groups?
@@ -2640,15 +2728,19 @@ If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
 
     ;; List dead groups.
     (and (>= level 8) (<= lowest 8)
-        (gnus-group-prepare-flat-list-dead gnus-zombie-list 8 ?Z))
+        (gnus-group-prepare-flat-list-dead 
+         (setq gnus-zombie-list (sort gnus-zombie-list 'string<)) 8 ?Z
+         regexp))
     (and (>= level 9) (<= lowest 9)
-        (gnus-group-prepare-flat-list-dead gnus-killed-list 9 ?K))
+        (gnus-group-prepare-flat-list-dead 
+         (setq gnus-killed-list (sort gnus-killed-list 'string<)) 9 ?K
+         regexp))
 
     (gnus-group-set-mode-line)
     (setq gnus-have-all-newsgroups all)
     (run-hooks 'gnus-group-prepare-hook)))
 
-(defun gnus-group-prepare-flat-list-dead (groups level mark)
+(defun gnus-group-prepare-flat-list-dead (groups level mark regexp)
   ;; List zombies and killed lists somehwat faster, which was
   ;; suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>. It does
   ;; this by ignoring the group format specification altogether.
@@ -2656,13 +2748,16 @@ If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
     (while groups
       (setq group (car groups)
            groups (cdr groups))
-      (setq beg (point))
-      (insert (format " %c    *: %s\n" mark group))
-      (add-text-properties 
-       beg (1+ beg) 
-       (list 'gnus-group (intern group)
-            'gnus-unread t
-            'gnus-level level)))))
+      (if (or (not regexp)
+             (string-match regexp group))
+         (progn
+           (setq beg (point))
+           (insert (format " %c    *: %s\n" mark group))
+           (add-text-properties 
+            beg (1+ beg) 
+            (list 'gnus-group (intern group)
+                  'gnus-unread t
+                  'gnus-level level)))))))
 
 (defun gnus-group-real-name (group)
   "Find the real name of a foreign newsgroup."
@@ -2699,6 +2794,25 @@ If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
 
 (defun gnus-group-set-info (info)
   (let ((entry (gnus-gethash (car info) gnus-newsrc-hashtb)))
+    (if entry
+       ()
+      (save-excursion
+       (set-buffer gnus-group-buffer)
+       (if (nth 4 info)
+           (gnus-group-make-group 
+            (gnus-group-real-name (car info))
+            (prin1-to-string (car (nth 4 info)))
+            (nth 1 (nth 4 info)))
+         (gnus-group-make-group
+          (car info)
+          (prin1-to-string (car gnus-select-method))
+          (nth 1 gnus-select-method)))
+       (message "Note: New group created")
+       (setq entry 
+             (gnus-gethash (gnus-group-prefixed-name 
+                            (gnus-group-real-name (car info))
+                            (or (nth 4 info) gnus-select-method))
+                           gnus-newsrc-hashtb))))
     (if entry
        (progn
          (setcar (nthcdr 2 entry) info)
@@ -2782,8 +2896,9 @@ moves the point to the colon."
         b)
     (beginning-of-line)
     (setq b (point))
-    ;; Insert the visible text.
-    (insert-before-markers (eval gformat))
+    ;; Insert the text.
+    (insert (eval gformat))
+
     (add-text-properties 
      b (1+ b) (list 'gnus-group (intern group)
                    'gnus-unread (if (numberp number)
@@ -2798,7 +2913,7 @@ If VISIBLE-ONLY is non-nil, the group won't be displayed if it isn't already."
   (save-excursion
     (set-buffer gnus-group-buffer)
     (let ((buffer-read-only nil)
-         (visible nil))
+         visible)
       (let ((entry (gnus-gethash group gnus-newsrc-hashtb)))
        (if entry
            (gnus-dribble-enter 
@@ -2835,13 +2950,10 @@ If VISIBLE-ONLY is non-nil, the group won't be displayed if it isn't already."
                               (point-min) (point-max) 
                               'gnus-group (intern (car (car entry)))))))
                  (setq entry (cdr entry)))
-               (or entry (goto-char (point-max))))))
-       (if (or visible (not visible-only))
-           (progn
-             (gnus-group-insert-group-line-info group)
-             (forward-line -1)         ; Move point back to the inserted line.
-             ))))
-    (gnus-group-set-mode-line)))
+               (or entry (goto-char (point-max)))))))
+      (if (or visible (not visible-only))
+         (gnus-group-insert-group-line-info group))
+      (gnus-group-set-mode-line))))
 
 (defun gnus-group-set-mode-line ()
   (if (memq 'group gnus-updated-mode-lines)
@@ -2890,7 +3002,7 @@ If FIRST-TOO, the current line is also eligeble as a target."
                            (let ((unread 
                                   (get-text-property (point) 'gnus-unread)))
                              (or (eq unread t) (and unread (> unread 0))))
-                           (> 5 (get-text-property (point) 'gnus-level))))
+                           (< (get-text-property (point) 'gnus-level) 6)))
                       (or (not level)
                           (let ((lev (get-text-property (point) 'gnus-level)))
                             (if (<= lev level)
@@ -3031,21 +3143,30 @@ done."
     (gnus-summary-position-cursor)
     (and best-point (gnus-group-group-name))))
 
-(defun gnus-group-add-group (name method address)
+(defun gnus-group-make-group (name method address)
   "Add a new newsgroup.
 The user will be prompted for a NAME, for a select METHOD, and an
 ADDRESS."
   (interactive
-   (list 
+   (cons 
     (read-string "Group name: ")
-    (completing-read (format "%s method: " name) 
-                    gnus-valid-select-methods nil t)
-    (read-string (format "Get %s by method %s from: " name method))))
-  (let ((nname (gnus-group-prefixed-name name (list (intern method) address))))
+    (let ((method
+          (completing-read 
+           "Method: " gnus-valid-select-methods nil t)))
+      (list method
+           (if (memq 'prompt-address
+                     (assoc method gnus-valid-select-methods))
+               (read-string "Address: ")
+             "")))))
+  (let ((nname (gnus-group-prefixed-name name (list (intern method) address)))
+       info)
     (gnus-group-change-level 
-     (list t nname 3 nil nil (list (intern method) address))
+     (setq info (list t nname 3 nil nil (list (intern method) address)))
      3 9 (gnus-gethash (or (gnus-group-group-name) "dummy.group")
                       gnus-newsrc-hashtb) t)
+    (gnus-sethash nname '(0 . 0) gnus-active-hashtb)
+    (gnus-dribble-enter 
+     (concat "(gnus-group-set-info '" (prin1-to-string (cdr info)) ")"))
     (gnus-group-insert-group-line-info nname)))
 
 (defun gnus-group-edit-group ()
@@ -3054,7 +3175,8 @@ ADDRESS."
        info)
     (if group (setq info (nth 2 (gnus-gethash group gnus-newsrc-hashtb)))
       (error "No group on current line"))
-    (switch-to-buffer (get-buffer-create gnus-group-edit-buffer))
+    (setq gnus-winconf-edit-group (current-window-configuration))
+    (pop-to-buffer (get-buffer-create gnus-group-edit-buffer))
     (gnus-add-current-to-buffer-list)
     (emacs-lisp-mode)
     ;; Suggested by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
@@ -3062,29 +3184,36 @@ ADDRESS."
     (local-set-key "\C-c\C-c" 'gnus-group-edit-group-done)
     (erase-buffer)
     (insert ";; Type `C-c C-c' after you have edited the newsgroup entry.\n\n")
-    (insert (format "(gnus-group-set-info\n  '%S)\n" info))))
+    (insert (pp-to-string (list 'gnus-group-set-info (list 'quote info))))))
 
 (defun gnus-group-edit-group-done ()
   (interactive)
   (set-buffer (get-buffer-create gnus-group-edit-buffer))
   (eval-current-buffer)
   (kill-buffer (current-buffer))
+  (and gnus-winconf-edit-group
+       (set-window-configuration gnus-winconf-edit-group))
+  (setq gnus-winconf-edit-group nil)
   (set-buffer gnus-group-buffer)
   (gnus-group-update-group (gnus-group-group-name))
   (gnus-group-position-cursor))
 
-(defun gnus-group-make-doc-group ()
+(defun gnus-group-make-help-group ()
   "Create the (ding) Gnus documentation group."
   (interactive)
+  (and (gnus-gethash (gnus-group-prefixed-name "gnus-help" '(nndoc ""))
+                    gnus-newsrc-hashtb)
+       (error "Documentation group already exists"))
   (let ((path load-path))
     (while (and path
                (not (file-exists-p (concat (file-name-as-directory (car path))
                                            "doc.txt"))))
       (setq path (cdr path)))
     (or path (error "Couldn't find doc group"))
-    (gnus-group-add-group 
-     "gnus-doc" "nndoc" 
-     (concat (file-name-as-directory (car path)) "doc.txt"))))
+    (gnus-group-make-group 
+     "gnus-help" "nndoc" 
+     (concat (file-name-as-directory (car path)) "doc.txt"))
+    (gnus-group-position-cursor)))
 
 (defun gnus-group-make-directory-group (dir)
   "Create an nndir group.
@@ -3095,7 +3224,69 @@ mail messages or news articles in files that have numeric names."
    (list (read-file-name "Create group from directory: ")))
   (or (file-exists-p dir) (error "No such directory"))
   (or (file-directory-p dir) (error "Not a directory"))
-  (gnus-group-add-group dir "nndir" dir))
+  (gnus-group-make-group dir "nndir" dir)
+  (gnus-group-position-cursor))
+
+(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
+score file entries for articles to include in the group."
+  (interactive
+   (list
+    (read-string "nnkiboze group name: ")
+    (read-string "Source groups (regexp): ")
+    (let ((headers (mapcar (lambda (group) (list group))
+                          '("subject" "from" "number" "date" "message-id"
+                            "references" "chars" "lines" "xref")))
+         scores header regexp regexps)
+      (while (not (equal "" (setq header (completing-read 
+                                         "Match on header: " headers nil t))))
+       (setq regexps nil)
+       (while (not (equal "" (setq regexp (read-string 
+                                           (format "Match on %s (string): "
+                                                   header)))))
+         (setq regexps (cons (list regexp nil 1000 nil) regexps)))
+       (setq scores (cons (cons header regexps) scores)))
+      (car scores))))
+  (gnus-group-make-group group "nnkiboze" address)
+  (save-excursion
+    (set-buffer (get-buffer-create " *gnus work*"))
+    (buffer-disable-undo (current-buffer))
+    (let (emacs-lisp-mode-hook)
+      (pp (list 'setq 'gnus-score-alist 
+               (list 'quote (list scores)))
+         (current-buffer)))
+    (write-region (point-min) (point-max) 
+                 (concat (or gnus-kill-files-directory "~/News")
+                         "nnkiboze:" group "." gnus-score-file-suffix))
+    (kill-buffer (current-buffer)))
+  (gnus-group-position-cursor))
+
+;; Group sorting commands
+;; Suggested by Joe Hildebrand <hildjj@idaho.fuentez.com>.
+
+(defun gnus-group-sort-groups ()
+  "Sort the group buffer using `gnus-group-sort-function'."
+  (interactive)
+  (setq gnus-newsrc-assoc 
+       (sort (cdr gnus-newsrc-assoc) gnus-group-sort-function))
+  (gnus-make-hashtable-from-newsrc-alist)
+  (gnus-get-unread-articles 6)
+  (gnus-group-list-groups 5))
+
+(defun gnus-group-sort-by-alphabet (info1 info2)
+  (string< (car info1) (car info2)))
+
+(defun gnus-group-sort-by-unread (info1 info2)
+  (let ((n1 (car (gnus-gethash (car info1) gnus-newsrc-hashtb)))
+       (n2 (car (gnus-gethash (car info2) gnus-newsrc-hashtb))))
+    (< (or (and (numberp n1) n1) 0)
+       (or (and (numberp n2) n2) 0))))
+
+(defun gnus-group-sort-by-level (info1 info2)
+  (< (nth 1 info1) (nth 1 info2)))
+
+;; Group catching up.
 
 (defun gnus-group-catchup-current (n &optional all)
   "Mark all articles not marked as unread in current newsgroup as read.
@@ -3197,7 +3388,8 @@ or nil if no action could be taken."
   (let ((group (gnus-group-group-name)))
     (or group (error "No newsgroup on current line"))
     (or arg (setq arg (if (<= (gnus-group-group-level) 5) 6 3)))
-    (gnus-group-unsubscribe-group group arg)))
+    (gnus-group-unsubscribe-group group arg)
+    (gnus-group-next-group 1)))
 
 (defun gnus-group-unsubscribe-group (group &optional level)
   "Toggle subscribe from/to unsubscribe GROUP.
@@ -3217,7 +3409,9 @@ New newsgroup is added to .newsrc automatically."
           (gnus-group-change-level 
            group 
            (if level level 3) 
-           (if (member group gnus-zombie-list) 8 9)
+           (or (nth 2 (nth 2 (gnus-gethash group gnus-newsrc-hashtb)))
+               (and (member group gnus-zombie-list) 8)
+               9)
            (or (and (gnus-group-group-name)
                     (gnus-gethash (gnus-group-group-name) gnus-newsrc-hashtb))
                (gnus-gethash (car (car gnus-newsrc-assoc)) 
@@ -3360,6 +3554,7 @@ Default is 7, which lists all subscribed and most unsubscribed groups."
 If ARG is non-nil, it should be a number between one and nine to
 specify which levels you are interested in re-scanning."
   (interactive "P")
+  (run-hooks 'gnus-get-new-news-hook)
   (if (and gnus-read-active-file (not arg))
       (progn
        (gnus-read-active-file)
@@ -3378,7 +3573,14 @@ If N is negative, this group and the N-1 previous groups will be checked."
        (w-p (window-start))
        group)
     (while (and (> n 0)
-               (gnus-get-new-news-in-group (gnus-group-group-name))
+               (progn
+                 (or (gnus-get-new-news-in-group
+                      (setq group (gnus-group-group-name)))
+                     (progn 
+                       (ding) 
+                       (message "%s error: %s" 
+                                group (gnus-status-message group))))
+                 t)
                (zerop (gnus-group-next-group way)))
       (setq n (1- n)))
     (if (/= 0 n) (message "No more newsgroups"))
@@ -3389,30 +3591,43 @@ If N is negative, this group and the N-1 previous groups will be checked."
     n))
 
 (defun gnus-get-new-news-in-group (group)
-  (if (and group (gnus-activate-newsgroup group))
-      (progn
-       (gnus-get-unread-articles-in-group 
-        (nth 2 (gnus-gethash group gnus-newsrc-hashtb))
-        (gnus-gethash group gnus-active-hashtb))
-       (gnus-group-update-group-line)))
-  t)
+  (and group 
+       (gnus-activate-newsgroup group)
+       (progn
+        (gnus-get-unread-articles-in-group 
+         (nth 2 (gnus-gethash group gnus-newsrc-hashtb))
+         (gnus-gethash group gnus-active-hashtb))
+        (gnus-group-update-group-line)
+        t)))
+
+(defun gnus-group-fetch-faq (group)
+  "Fetch the FAQ for the current group."
+  (interactive (list (gnus-group-group-name)))
+  (or group (error "No group name given"))
+  (let ((file (concat gnus-group-faq-directory group))) 
+    (if (not (file-exists-p file))
+       (error "No such file: %s" file)
+      (find-file file))))
   
-(defun gnus-group-describe-group (&optional group)
+(defun gnus-group-describe-group (force &optional group)
   "Display a description of the current newsgroup."
-  (interactive)
-  (let ((group (or group (gnus-group-group-name))))
-    (if (not group)
-       (message "No group on current line")
-      (and (or gnus-description-hashtb
-              (gnus-read-descriptions-file))
-          (message
-           (or (gnus-gethash group gnus-description-hashtb)
-               "No description available"))))))
+  (interactive "P")
+  (and force (setq gnus-description-hashtb nil))
+  (let ((group (or group (gnus-group-group-name)))
+       desc)
+    (or group (message "No group name given"))
+    (and (or gnus-description-hashtb
+            (setq desc (gnus-group-get-description group))
+            (gnus-read-descriptions-file))
+        (message
+         (or desc (gnus-gethash group gnus-description-hashtb)
+             "No description available")))))
 
 ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-group-describe-all-groups ()
+(defun gnus-group-describe-all-groups (force)
   "Pop up a buffer with descriptons of all newsgroups."
-  (interactive)
+  (interactive "P")
+  (and force (setq gnus-description-hashtb nil))
   (if (not (or gnus-description-hashtb
               (gnus-read-descriptions-file)))
       (error "Couldn't request descriptions file"))
@@ -3481,60 +3696,26 @@ If N is negative, this group and the N-1 previous groups will be checked."
       (error "Couldn't request descriptions file"))
   (gnus-group-apropos regexp t))
 
-;; Written by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-group-list-matching (regexp) 
-  "List all newsgroups with unread articles that match REGEXP."
-  (interactive "sList newsgroups matching: ")
-  (set-buffer gnus-group-buffer)
-  (let ((buffer-read-only nil)
-       (newsrc (cdr gnus-newsrc-assoc))
-       (zombie gnus-zombie-list)
-       (killed gnus-killed-list)
-       info unread active group)
-    (erase-buffer)
-
-    ;; List alive newsgroups.
-    (while newsrc
-      (setq info (car newsrc)
-           group (car info)
-           newsrc (cdr newsrc)
-           unread (car (gnus-gethash group gnus-newsrc-hashtb)))
-      (if (and unread ; This group might be bogus
-              (string-match regexp group))
-         (gnus-group-insert-group-line 
-          nil group (car (cdr info)) (nth 3 info) unread
-          (nth 4 info))))
-
-    ;; List zombies and killed lists.
-    (let ((lists (list 'gnus-zombie-list 'gnus-killed-list))
-         mark b)
-      (while lists
-       (if (eq (car lists) 'gnus-zombie-list)
-           (setq mark ?Z)
-         (setq mark ?K))
-       (setq newsrc (set (car lists)
-                         (sort (symbol-value (car lists)) 
-                               (function string<))))
-       (while newsrc
-         (setq group (car newsrc)
-               newsrc (cdr newsrc))
-         (if (not (string-match regexp group))
-             ()
-           (setq b (point))
-           (insert (format " %c    *: %s" mark group))
-           (add-text-properties 
-            b (1+ b) 
-            (list 'gnus-group (intern group)
-                  'gnus-unread t
-                  'gnus-level (if (= mark ?Z) 8 9)))))
-       (setq lists (cdr lists))))
-
-    (gnus-group-set-mode-line)
-    (setq gnus-have-all-newsgroups t)
-    (run-hooks 'gnus-group-prepare-hook))
+;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
+(defun gnus-group-list-matching (level regexp &optional all lowest) 
+  "List all groups with unread articles that match REGEXP.
+If the prefix LEVEL is non-nil, it should be a number that says which
+level to cut off listing groups. 
+If ALL, also list groups with no unread articles.
+If LOWEST, don't list groups with level lower than LOWEST."
+  (interactive "P\nsList newsgroups matching: ")
+  (gnus-group-prepare-flat (or level 5) all (or lowest 1) regexp)
   (goto-char (point-min))
   (gnus-group-position-cursor))
 
+(defun gnus-group-list-all-matching (level regexp &optional lowest) 
+  "List all groups that match REGEXP.
+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."
+  (interactive "P\nsList newsgroups matching: ")
+  (gnus-group-list-matching (or level 9) regexp t lowest))
+
 ;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
 (defun gnus-group-save-newsrc ()
   "Save the Gnus startup files."
@@ -3564,23 +3745,20 @@ If N is negative, this group and the N-1 previous groups will be checked."
   (interactive)
   (mail))
 
-(defun gnus-group-edit-global-kill ()
-  "Edit a global kill file."
-  (interactive)
-  (setq gnus-current-kill-article nil) ;No articles selected.
-  (gnus-kill-file-edit-file nil)       ;Nil stands for global KILL file.
+(defun gnus-group-edit-global-kill (article &optional group)
+  "Edit the global kill file.
+If GROUP, edit that local kill file instead."
+  (interactive "P")
+  (setq gnus-current-kill-article article)
+  (gnus-kill-file-edit-file group)
   (message
    (substitute-command-keys
     "Editing a global kill file (Type \\[gnus-kill-file-exit] to exit)")))
 
-(defun gnus-group-edit-local-kill ()
+(defun gnus-group-edit-local-kill (article group)
   "Edit a local kill file."
-  (interactive)
-  (setq gnus-current-kill-article nil) ;No articles selected.
-  (gnus-kill-file-edit-file (gnus-group-group-name))
-  (message
-   (substitute-command-keys
-    "Editing a local kill file (Type \\[gnus-kill-file-exit] to exit)")))
+  (interactive (list nil (gnus-group-group-name)))
+  (gnus-group-edit-global-kill article group))
 
 (defun gnus-group-force-update ()
   "Update `.newsrc' file."
@@ -3597,6 +3775,7 @@ The hook gnus-suspend-gnus-hook is called before actually suspending."
   (let ((group-buf (get-buffer gnus-group-buffer)))
     (while gnus-buffer-list
       (and (not (eq (get-buffer (car gnus-buffer-list)) group-buf))
+          (not (eq (get-buffer (car gnus-buffer-list)) gnus-dribble-buffer))
           (get-buffer (car gnus-buffer-list))
           (buffer-name (get-buffer (car gnus-buffer-list)))
           (kill-buffer (car gnus-buffer-list)))
@@ -3623,8 +3802,18 @@ The hook `gnus-exit-gnus-hook' is called before actually exiting."
       (progn
        (run-hooks 'gnus-exit-gnus-hook)
        (gnus-save-newsrc-file)
+       (gnus-close-backends)
        (gnus-clear-system))))
 
+(defun gnus-close-backends ()
+  (let ((methods gnus-valid-select-methods)
+       func)
+    (while methods
+      (if (fboundp (setq func (intern (concat (car (car methods))
+                                             "-request-close"))))
+         (funcall func))
+      (setq methods (cdr methods)))))
+
 (defun gnus-group-quit ()
   "Quit reading news without updating .newsrc.eld or .newsrc.
 The hook `gnus-exit-gnus-hook' is called before actually exiting."
@@ -3640,6 +3829,7 @@ The hook `gnus-exit-gnus-hook' is called before actually exiting."
       (progn
        (run-hooks 'gnus-exit-gnus-hook)
        (gnus-dribble-save)
+       (gnus-close-backends)
        (gnus-clear-system))))
 
 (defun gnus-group-describe-briefly ()
@@ -3681,16 +3871,16 @@ and the second element is the address."
   (define-key gnus-browse-server-mode-map "=" 'gnus-browse-read-group)
   (define-key gnus-browse-server-mode-map "n" 'gnus-browse-next-group)
   (define-key gnus-browse-server-mode-map "p" 'gnus-browse-prev-group)
-  (define-key gnus-browse-server-mode-map [del] 'gnus-browse-prev-group)
+  (define-key gnus-browse-server-mode-map "\177" 'gnus-browse-prev-group)
   (define-key gnus-browse-server-mode-map "N" 'gnus-browse-next-group)
-  (define-key gnus-browse-server-mode-map "P" 'gnus-group-prev-group)
+  (define-key gnus-browse-server-mode-map "P" 'gnus-browse-prev-group)
   (define-key gnus-browse-server-mode-map "\M-n" 'gnus-browse-next-group)
   (define-key gnus-browse-server-mode-map "\M-p" 'gnus-browse-prev-group)
   (define-key gnus-browse-server-mode-map "\r" 'gnus-browse-read-group)
   (define-key gnus-browse-server-mode-map "u" 'gnus-browse-unsubscribe-current-group)
   (define-key gnus-browse-server-mode-map "q" 'gnus-browse-exit)
   (define-key gnus-browse-server-mode-map "Q" 'gnus-browse-exit)
-  (define-key gnus-browse-server-mode-map "\C-c\C-c" 'gnus-browse-quit)
+  (define-key gnus-browse-server-mode-map "\C-c\C-c" 'gnus-browse-exit)
   (define-key gnus-browse-server-mode-map "?" 'gnus-browse-describe-briefly)
   (define-key gnus-browse-server-mode-map "\C-c\C-i" 'gnus-info-find-node)
   )
@@ -3717,6 +3907,7 @@ and the second element is the address."
       (set-buffer nntp-server-buffer)
       (let ((cur (current-buffer)))
        (goto-char 1)
+       (delete-matching-lines gnus-ignored-newsgroups)
        (while (re-search-forward 
                "\\(^[^ \t]+\\)[ \t]+[0-9]+[ \t]+[0-9]+" nil t)
          (goto-char (match-end 1))
@@ -3738,7 +3929,7 @@ and the second element is the address."
     (gnus-group-position-cursor)))
 
 (defun gnus-browse-server-mode ()
-  "Major mode for reading network news."
+  "Major mode for browsing a foreign server."
   (interactive)
   (kill-all-local-variables)
   (setq mode-line-modified "-- ")
@@ -3785,7 +3976,7 @@ and the second element is the address."
                (zerop (gnus-browse-next-group ward)))
       (setq arg (1- arg)))
     (gnus-group-position-cursor)
-    (if (/= 0 arg) (message "No more newsgroups" ))
+    (if (/= 0 arg) (message "No more newsgroups"))
     arg))
   
 (defun gnus-browse-unsubscribe-group ()
@@ -3833,6 +4024,7 @@ and the second element is the address."
 
 (defvar gnus-summary-mode-map nil)
 (defvar gnus-summary-mark-map nil)
+(defvar gnus-summary-mscore-map nil)
 (defvar gnus-summary-send-map nil)
 (defvar gnus-summary-extract-map nil)
 (defvar gnus-summary-extract-view-map nil)
@@ -3843,18 +4035,21 @@ and the second element is the address."
 (defvar gnus-summary-various-map nil)
 (defvar gnus-summary-interest-map nil)
 (defvar gnus-summary-process-map nil)
+(defvar gnus-summary-score-map nil)
 (defvar gnus-summary-sort-map nil)
 (defvar gnus-summary-mgroup-map nil)
 (defvar gnus-summary-vkill-map nil)
 (defvar gnus-summary-increase-map nil)
 (defvar gnus-summary-inc-subject-map nil)
 (defvar gnus-summary-inc-author-map nil)
+(defvar gnus-summary-inc-id-map nil)
 (defvar gnus-summary-inc-xref-map nil)
 (defvar gnus-summary-inc-thread-map nil)
 (defvar gnus-summary-inc-fol-map nil)
 (defvar gnus-summary-lower-map nil)
 (defvar gnus-summary-low-subject-map nil)
 (defvar gnus-summary-low-author-map nil)
+(defvar gnus-summary-low-id-map nil)
 (defvar gnus-summary-low-xref-map nil)
 (defvar gnus-summary-low-thread-map nil)
 (defvar gnus-summary-low-fol-map nil)
@@ -3864,7 +4059,7 @@ and the second element is the address."
   (setq gnus-summary-mode-map (make-keymap))
   (suppress-keymap gnus-summary-mode-map)
 
-  ;;Non-orthogonal keys
+  ;; Non-orthogonal keys
 
   (define-key gnus-summary-mode-map " " 'gnus-summary-next-page)
   (define-key gnus-summary-mode-map "\177" 'gnus-summary-prev-page)
@@ -3924,7 +4119,6 @@ and the second element is the address."
   (define-key gnus-summary-mode-map "w" 'gnus-summary-stop-page-breaking)
   (define-key gnus-summary-mode-map "\C-c\C-r" 'gnus-summary-caesar-message)
   (define-key gnus-summary-mode-map "\M-t" 'gnus-summary-toggle-mime)
-  (define-key gnus-summary-mode-map "\C-d" 'gnus-summary-enter-digest-group)
   (define-key gnus-summary-mode-map "f" 'gnus-summary-followup)
   (define-key gnus-summary-mode-map "F" 'gnus-summary-followup-with-original)
   (define-key gnus-summary-mode-map "C" 'gnus-summary-cancel-article)
@@ -3945,7 +4139,7 @@ and the second element is the address."
   (define-key gnus-summary-mode-map "m" 'gnus-summary-mail-other-window)
   (define-key gnus-summary-mode-map "a" 'gnus-summary-post-news)
   (define-key gnus-summary-mode-map "x" 'gnus-summary-delete-marked-as-read)
-  (define-key gnus-summary-mode-map "X" 'gnus-summary-remove-lines-marked-with)
+; (define-key gnus-summary-mode-map "X" 'gnus-summary-remove-lines-marked-with)
   (define-key gnus-summary-mode-map "s" 'gnus-summary-isearch-article)
   (define-key gnus-summary-mode-map "t" 'gnus-summary-toggle-header)
   (define-key gnus-summary-mode-map "g" 'gnus-summary-show-article)
@@ -3954,7 +4148,7 @@ and the second element is the address."
   (define-key gnus-summary-mode-map "\C-c\C-v\C-v" 'gnus-uu-decode-uu)
 
 
-  ;; Orthogonal keymap
+  ;; Sort of orthogonal keymap
   (define-prefix-command 'gnus-summary-mark-map)
   (define-key gnus-summary-mode-map "M" 'gnus-summary-mark-map)
   (define-key gnus-summary-mark-map "t" 'gnus-summary-tick-article-forward)
@@ -3973,12 +4167,18 @@ and the second element is the address."
   (define-key gnus-summary-mark-map "\M-r" 'gnus-summary-remove-lines-marked-as-read)
   (define-key gnus-summary-mark-map "\M-\C-r" 'gnus-summary-remove-lines-marked-with)
   (define-key gnus-summary-mark-map "D" 'gnus-summary-show-all-dormant)
+  (define-key gnus-summary-mark-map "\M-D" 'gnus-summary-hide-all-dormant)
   (define-key gnus-summary-mark-map "S" 'gnus-summary-show-all-expunged)
   (define-key gnus-summary-mark-map "C" 'gnus-summary-catchup)
   (define-key gnus-summary-mark-map "H" 'gnus-summary-catchup-to-here)
   (define-key gnus-summary-mark-map "\C-c" 'gnus-summary-catchup-all)
-  (define-key gnus-summary-mark-map "a" 'gnus-summary-clear-above)
-  (define-key gnus-summary-mark-map "A" 'gnus-summary-tick-above)
+
+  (define-prefix-command 'gnus-summary-mscore-map)
+  (define-key gnus-summary-mark-map "s" 'gnus-summary-mscore-map)
+  (define-key gnus-summary-mscore-map "c" 'gnus-summary-clear-above)
+  (define-key gnus-summary-mscore-map "u" 'gnus-summary-tick-above)
+  (define-key gnus-summary-mscore-map "m" 'gnus-summary-mark-above)
+  (define-key gnus-summary-mscore-map "k" 'gnus-summary-kill-below)
 
   (define-prefix-command 'gnus-summary-process-map)
   (define-key gnus-summary-mark-map "p" 'gnus-summary-process-map)
@@ -4024,13 +4224,14 @@ and the second element is the address."
   (define-key gnus-summary-goto-map "b" 'gnus-summary-best-unread-article)
   (define-key gnus-summary-goto-map "g" 'gnus-summary-goto-subject)
   (define-key gnus-summary-goto-map "l" 'gnus-summary-goto-last-article)
+  (define-key gnus-summary-goto-map "p" 'gnus-summary-pop-article)
 
 
   (define-prefix-command 'gnus-summary-thread-map)
   (define-key gnus-summary-mode-map "T" 'gnus-summary-thread-map)
   (define-key gnus-summary-thread-map "k" 'gnus-summary-kill-thread)
   (define-key gnus-summary-thread-map "l" 'gnus-summary-lower-thread)
-  (define-key gnus-summary-thread-map "r" 'gnus-summary-raise-thread)
+  (define-key gnus-summary-thread-map "i" 'gnus-summary-raise-thread)
   (define-key gnus-summary-thread-map "T" 'gnus-summary-toggle-threads)
   (define-key gnus-summary-thread-map "s" 'gnus-summary-show-thread)
   (define-key gnus-summary-thread-map "S" 'gnus-summary-show-all-threads)
@@ -4085,7 +4286,6 @@ and the second element is the address."
   (define-key gnus-summary-mode-map "X" 'gnus-summary-extract-map)
 ;  (define-key gnus-summary-extract-map "x" 'gnus-summary-extract-any)
 ;  (define-key gnus-summary-extract-map "m" 'gnus-summary-extract-mime)
-
   (define-key gnus-summary-extract-map "u" 'gnus-uu-decode-uu)
   (define-key gnus-summary-extract-map "U" 'gnus-uu-decode-uu-and-save)
   (define-key gnus-summary-extract-map "s" 'gnus-uu-decode-unshar)
@@ -4110,25 +4310,32 @@ and the second element is the address."
   (define-prefix-command 'gnus-summary-various-map)
   (define-key gnus-summary-mode-map "V" 'gnus-summary-various-map)
   (define-key gnus-summary-various-map "u" 'gnus-summary-universal-argument)
-  (define-key gnus-summary-various-map "\M-s" 'gnus-summary-search-article-forward)
-  (define-key gnus-summary-various-map "\M-r" 'gnus-summary-search-article-backward)
+  (define-key gnus-summary-various-map "\C-s" 'gnus-summary-search-article-forward)
+  (define-key gnus-summary-various-map "\C-r" 'gnus-summary-search-article-backward)
   (define-key gnus-summary-various-map "r" 'gnus-summary-refer-article)
   (define-key gnus-summary-various-map "&" 'gnus-summary-execute-command)
-  (define-key gnus-summary-various-map "\C-t" 'gnus-summary-toggle-truncation)
-  (define-key gnus-summary-various-map "=" 'gnus-summary-expand-window)
-  (define-key gnus-summary-various-map "\C-s" 'gnus-summary-reselect-current-group)
+  (define-key gnus-summary-various-map "T" 'gnus-summary-toggle-truncation)
+  (define-key gnus-summary-various-map "e" 'gnus-summary-expand-window)
+  (define-key gnus-summary-various-map "S" 'gnus-summary-reselect-current-group)
   (define-key gnus-summary-various-map "g" 'gnus-summary-rescan-group)
   (define-key gnus-summary-various-map "o" 'gnus-summary-save-article)
   (define-key gnus-summary-various-map "\C-o" 'gnus-summary-save-article-mail)
   (define-key gnus-summary-various-map "|" 'gnus-summary-pipe-output)
   (define-key gnus-summary-various-map "V" 'gnus-version)
+  (define-key gnus-summary-various-map "f" 'gnus-summary-fetch-faq)
   (define-key gnus-summary-various-map "d" 'gnus-summary-describe-group)
   (define-key gnus-summary-various-map "?" 'gnus-summary-describe-briefly)
   (define-key gnus-summary-various-map "i" 'gnus-info-find-node)
-  (define-key gnus-summary-various-map "S" 'gnus-summary-set-score)
-  (define-key gnus-summary-various-map "b" 'gnus-summary-set-mark-below)
   (define-key gnus-summary-various-map "D" 'gnus-summary-enter-digest-group)
 
+  (define-prefix-command 'gnus-summary-score-map)
+  (define-key gnus-summary-various-map "S" 'gnus-summary-score-map)
+  (define-key gnus-summary-score-map "s" 'gnus-summary-set-score)
+  (define-key gnus-summary-score-map "c" 'gnus-score-change-score-file)
+  (define-key gnus-summary-score-map "m" 'gnus-score-set-mark-below)
+  (define-key gnus-summary-score-map "E" 'gnus-score-set-expunge-below)
+  (define-key gnus-summary-score-map "e" 'gnus-score-edit-file)
+
   (define-prefix-command 'gnus-summary-sort-map)
   (define-key gnus-summary-various-map "s" 'gnus-summary-sort-map)
   (define-key gnus-summary-sort-map "n" 'gnus-summary-sort-by-number)
@@ -4144,6 +4351,7 @@ and the second element is the address."
   (define-key gnus-summary-mgroup-map "m" 'gnus-summary-move-article)
   (define-key gnus-summary-mgroup-map "r" 'gnus-summary-respool-article)
   (define-key gnus-summary-mgroup-map "w" 'gnus-summary-edit-article)
+  (define-key gnus-summary-mgroup-map "c" 'gnus-summary-copy-article)
 
   (define-prefix-command 'gnus-summary-vkill-map)
   (define-key gnus-summary-various-map "k" 'gnus-summary-vkill-map)
@@ -4151,9 +4359,6 @@ and the second element is the address."
   (define-key gnus-summary-vkill-map "K" 'gnus-summary-kill-same-subject)
   (define-key gnus-summary-vkill-map "\M-k" 'gnus-summary-edit-local-kill)
   (define-key gnus-summary-vkill-map "\M-K" 'gnus-summary-edit-global-kill)
-  (define-key gnus-summary-vkill-map "x" 'gnus-kill-file-set-expunge-below)
-  (define-key gnus-summary-vkill-map "m" 'gnus-kill-file-set-mark-below)
-
 
 
   (define-prefix-command 'gnus-summary-increase-map)
@@ -4178,6 +4383,14 @@ and the second element is the address."
   (define-key gnus-summary-inc-author-map "t" 'gnus-summary-temporarily-raise-by-author)
   (define-key gnus-summary-inc-author-map "p" 'gnus-summary-raise-by-author)
 
+  (define-prefix-command 'gnus-summary-inc-id-map)
+  (define-key gnus-summary-increase-map "i" 'gnus-summary-inc-id-map)
+  (define-key gnus-summary-increase-map "I" 'gnus-summary-temporarily-raise-by-id)
+  (define-key gnus-summary-inc-id-map "i" 'gnus-summary-temporarily-raise-by-id)
+  (define-key gnus-summary-inc-id-map "I" 'gnus-summary-raise-by-id)
+  (define-key gnus-summary-inc-id-map "t" 'gnus-summary-temporarily-raise-by-id)
+  (define-key gnus-summary-inc-id-map "p" 'gnus-summary-raise-by-id)
+
   (define-prefix-command 'gnus-summary-inc-thread-map)
   (define-key gnus-summary-increase-map "t" 'gnus-summary-inc-thread-map)
   (define-key gnus-summary-increase-map "T" 'gnus-summary-temporarily-raise-by-thread)
@@ -4224,6 +4437,14 @@ and the second element is the address."
   (define-key gnus-summary-low-author-map "t" 'gnus-summary-temporarily-lower-by-author)
   (define-key gnus-summary-low-author-map "p" 'gnus-summary-lower-by-author)
 
+  (define-prefix-command 'gnus-summary-low-id-map)
+  (define-key gnus-summary-lower-map "i" 'gnus-summary-low-id-map)
+  (define-key gnus-summary-lower-map "I" 'gnus-summary-temporarily-lower-by-id)
+  (define-key gnus-summary-low-id-map "i" 'gnus-summary-temporarily-lower-by-id)
+  (define-key gnus-summary-low-id-map "I" 'gnus-summary-lower-by-id)
+  (define-key gnus-summary-low-id-map "t" 'gnus-summary-temporarily-lower-by-id)
+  (define-key gnus-summary-low-id-map "p" 'gnus-summary-lower-by-id)
+
   (define-prefix-command 'gnus-summary-low-thread-map)
   (define-key gnus-summary-lower-map "t" 'gnus-summary-low-thread-map)
   (define-key gnus-summary-lower-map "T" 'gnus-summary-temporarily-lower-by-thread)
@@ -4253,128 +4474,11 @@ and the second element is the address."
 \f
 
 (defun gnus-summary-mode ()
-  "Major mode for reading articles in this newsgroup.
+  "Major mode for reading articles.
 All normal editing commands are switched off.
 The following commands are available:
 
-\\<gnus-summary-mode-map>
-\\[gnus-summary-next-page]\t Scroll the article buffer a page forwards
-\\[gnus-summary-prev-page]\t Scroll the article buffer a page backwards
-\\[gnus-summary-scroll-up]\t Scroll the article buffer one line forwards
-\\[gnus-summary-next-unread-article]\t Go to the next unread article
-\\[gnus-summary-prev-unread-article]\t Go to the previous unread article
-\\[gnus-summary-next-article]\t Go to the next article
-\\[gnus-summary-prev-article]\t Go to the previous article
-\\[gnus-summary-next-same-subject]\t Go to the next summary line with the same subject
-\\[gnus-summary-prev-same-subject]\t Go to the previous summary line with the same subject
-\\[gnus-summary-next-subject]\t Go to the next summary line
-\\[gnus-summary-prev-subject]\t Go to the previous summary line
-\\[gnus-summary-next-unread-subject]\t Go to the next unread summary line
-\\[gnus-summary-prev-unread-subject]\t Go to the previous unread summary line
-\\[gnus-summary-first-unread-article]\t Go to the first unread article
-\\[gnus-summary-best-unread-article]\t Go to the unread article with the highest score
-\\[gnus-summary-goto-subject]\t Go to some subject
-\\[gnus-summary-goto-last-article]\t Go to the previous article
-
-\\[gnus-summary-beginning-of-article]\t Go to the beginning of the article
-\\[gnus-summary-end-of-article]\t Go to the end of the article
-
-\\[gnus-summary-refer-parent-article]\t Get the parent of the current article from the server
-\\[gnus-summary-refer-article]\t Request some article by Message-ID from the server
-
-\\[gnus-summary-isearch-article]\t Do an interactive search on the current article
-\\[gnus-summary-search-article-forward]\t Search all articles forward for a regular expression
-\\[gnus-summary-search-article-backward]\t Search all articles backward for a regular expression
-
-\\[gnus-summary-tick-article-forward]\t Tick current article and move forward
-\\[gnus-summary-tick-article-backward]\t Tick current article and move backward
-\\[gnus-summary-mark-as-read-forward]\t Mark the current article as read and move forward
-\\[gnus-summary-mark-as-read-backward]\t Mark the current article as read and move backward
-\\[gnus-summary-clear-mark-forward]\t Clear tick and read marks and move forward
-\\[gnus-summary-clear-mark-backward]\t Clear tick and read marks and move backward
-\\[gnus-summary-mark-as-processable]\t Set the process mark on the current article
-\\[gnus-summary-unmark-as-processable]\t Remove the process mark from the current article
-\\[gnus-summary-unmark-all-processable]\t Remove the process mark from all articles
-
-\\[gnus-summary-raise-same-subject-and-select]\t Raise all articles with the current subject and select the next article
-\\[gnus-summary-raise-same-subject]\t Raise all articles with the current subject
-\\[gnus-summary-lower-same-subject-and-select]\t Lower all articles with the current subject and select the next article
-\\[gnus-summary-lower-same-subject]\t Lower all articles with the current subject
-
-\\[gnus-summary-toggle-threads]\t Toggle thread display
-\\[gnus-summary-show-thread]\t Show the current thread
-\\[gnus-summary-hide-thread]\t Hide the current thread
-\\[gnus-summary-next-thread]\t Go to the next thread
-\\[gnus-summary-prev-thread]\t Go to the previous thread
-\\[gnus-summary-up-thread]\t Go up the current thread
-\\[gnus-summary-down-thread]\t Descend the current thread
-\\[gnus-summary-raise-thread]\t Raise the current thread
-\\[gnus-summary-lower-thread]\t Lower the current thread
-\\[gnus-summary-mark-as-expirable]\t Mark the current artivles as expirable
-\\[gnus-summary-remove-lines-marked-as-read]\t Remove all articles that are marked as read
-\\[gnus-summary-remove-lines-marked-with]\t Remove all articles that have some mark
-
-\\[gnus-summary-execute-command]\t Execute a command
-\\[gnus-summary-catchup-and-exit]\t Mark all unread articles as read and exit
-\\[gnus-summary-toggle-truncation]\t Toggle truncation of summary lines
-\\[gnus-summary-expand-window]\t Expand the summary window
-\\[gnus-summary-universal-argument]\t Run a command on all articles with the process mark
-
-\\[gnus-summary-sort-by-number]\t Sort the summary buffer by article number
-\\[gnus-summary-sort-by-author]\t Sort the summary buffer by author
-\\[gnus-summary-sort-by-subject]\t Sort the summary buffer by subject
-\\[gnus-summary-sort-by-date]\t Sort the summary buffer by date
-
-\\[gnus-summary-reselect-current-group]\t Exit and reselect the current group
-\\[gnus-summary-rescan-group]\t Exit, get new articles and reselect the group
-\\[gnus-summary-stop-page-breaking]\t Stop page breaking of the current article
-\\[gnus-summary-caesar-message]\t Caesar rotate (rot13) the current article
-\\[gnus-summary-show-article]\t Reselect the current article
-\\[gnus-summary-toggle-header]\t Toggle header display
-\\[gnus-summary-toggle-mime]\t Toggle whether to use MIME
-\\[gnus-summary-enter-digest-group]\t Enter a newsgroup based on the current digest
-\\[gnus-summary-post-news]\t Post an article to the current group
-\\[gnus-summary-followup]\t Post a followup to the current article
-\\[gnus-summary-followup-with-original]\t Post a followup and include the original article
-\\[gnus-summary-cancel-article]\t Cancel the current article
-\\[gnus-summary-supersede-article]\t Supersede the current article
-\\[gnus-summary-reply]\t Mail a reply to the author of the current article
-\\[gnus-summary-reply-with-original]\t Mail a reply and include the current article
-\\[gnus-summary-mail-forward]\t Forward the current article
-\\[gnus-summary-mail-other-window]\t Mail in the other window
-\\[gnus-summary-save-article]\t Save the current article
-\\[gnus-summary-save-article-mail]\t Save the current article in rmail format
-\\[gnus-summary-pipe-output]\t Pipe the current article to a process
-\\[gnus-summary-move-article]\t Move the article to a different newsgroup
-\\[gnus-summary-respool-article]\t Respool the article
-\\[gnus-summary-edit-local-kill]\t Edit the local kill file
-\\[gnus-summary-edit-global-kill]\t Edit the global kill file
-\\[gnus-version]\t Display the current Gnus version
-\\[gnus-summary-exit]\t Exit the summary buffer 
-\\[gnus-summary-quit]\t Exit the summary buffer without saving any changes
-\\[gnus-summary-describe-group]\t Describe the current newsgroup
-\\[gnus-summary-describe-briefly]\t Give a brief key overview
-\\[gnus-info-find-node]\t Go to the Gnus info node
-
-\\[gnus-kill-file-set-expunge-below]   Automatically expunge articles below LEVEL.
-
-\\[gnus-kill-file-set-mark-below]      Automatically mark articles below LEVEL.
-\\[gnus-summary-temporarily-raise-by-subject]\t Temporarily raise score for articles with the current subject
-\\[gnus-summary-temporarily-raise-by-author]\t Temporarily raise score for articles from the current author
-\\[gnus-summary-temporarily-raise-by-xref]\t Temporarily raise score for articles with the current cross-posting
-\\[gnus-summary-raise-by-subject]\t Permanently raise score for articles with the current subject
-\\[gnus-summary-raise-by-author]\t Permanently raise score for articles from the current author
-\\[gnus-summary-raise-followups-to-author]\t Permanently raise score for followups to the current author
-\\[gnus-summary-raise-by-xref]\t Permanently raise score for articles with the current cross-posting
-\\[gnus-summary-temporarily-lower-by-subject]\t Temporarily lower score for articles with the current subject
-\\[gnus-summary-temporarily-lower-by-author]\t Temporarily lower score for articles from the current author
-\\[gnus-summary-temporarily-lower-by-xref]\t Temporarily lower score for articles with the current cross-posting
-\\[gnus-summary-lower-by-subject]\t Permanently lower score for articles with the current subject
-\\[gnus-summary-lower-by-author]\t Permanently lower score for articles from the current author
-\\[gnus-summary-lower-followups-to-author]\t Permanently lower score for followups to the current author
-\\[gnus-summary-lower-by-thread]\t Permanently lower score for articles in the current thread
-\\[gnus-summary-lower-by-xref]\t Permanently lower score for articles with the current cross-posting
-"
+\\{gnus-summary-mode-map}"
   (interactive)
   (if gnus-visual (gnus-summary-make-menu-bar))
   (kill-all-local-variables)
@@ -4396,9 +4500,6 @@ The following commands are available:
   (setq major-mode 'gnus-summary-mode)
   (setq mode-name "Summary")
   (make-local-variable 'minor-mode-alist)
-;  (or (assq 'gnus-show-threads minor-mode-alist)
-;      (setq minor-mode-alist
-;          (cons (list 'gnus-show-threads " Thread") minor-mode-alist)))
   (gnus-set-mode-line 'summary)
   (use-local-map gnus-summary-mode-map)
   (buffer-disable-undo (current-buffer))
@@ -4408,6 +4509,14 @@ The following commands are available:
   (setq selective-display-ellipses t)  ;Display `...'
   (run-hooks 'gnus-summary-mode-hook))
 
+(defun gnus-summary-clear-local-variables ()
+  (let ((locals gnus-summary-local-variables))
+    (while locals
+      (if (consp (car locals))
+         (set (car (car locals)) nil)
+       (set (car locals) nil))
+      (setq locals (cdr locals)))))
+
 (defun gnus-mouse-pick-article (e)
   (interactive "e")
   (mouse-set-point e)
@@ -4461,12 +4570,13 @@ The following commands are available:
          (make-string (* level gnus-thread-indent-level) ? ))
         (lines (or (header-lines header) 0))
         (score (or score gnus-summary-default-score 0))
-        (score-char (if (= score gnus-summary-default-score) ? 
+        (score-char (if (or (null gnus-summary-default-score)
+                            (= score gnus-summary-default-score)) ? 
                       (if (< score gnus-summary-default-score) 
                           gnus-score-below-mark gnus-score-over-mark)))
         (replied (if replied gnus-replied-mark ? ))
         (from (header-from header))
-        (name-address (gnus-extract-address-components from))
+        (name-address (funcall gnus-extract-address-components from))
         (address (car (cdr name-address)))
         (name (or (car name-address) (car (cdr name-address))))
         (number (header-number header))
@@ -4479,7 +4589,7 @@ The following commands are available:
     (if (not (numberp lines)) (setq lines 0))
     (beginning-of-line)
     (setq b (point))
-    (insert-before-markers (eval sformat))
+    (insert (eval sformat))
     (add-text-properties
      b (1+ b)
      (list 'gnus-subject (gnus-simplify-subject-re subject)
@@ -4487,33 +4597,31 @@ The following commands are available:
           'gnus-mark (or unread gnus-unread-mark ? )
           'gnus-thread level))))
 
-(defun gnus-summary-update-line ()
+(defun gnus-summary-update-line (&optional dont-update)
   ;; Update summary line after change.
   (or (not gnus-summary-default-score)
       gnus-summary-inhibit-highlight
-      (save-excursion
-       (beginning-of-line 1)
-       (let ((score (gnus-summary-article-score))
-             (default gnus-summary-default-score)
-             (below gnus-summary-mark-below))
-         (save-excursion
-           (if (< score below)
-               (if (eq (following-char) gnus-unread-mark)
-                   (gnus-summary-mark-article nil gnus-low-score-mark))
-             (if (eq (following-char) gnus-low-score-mark)
-                 (gnus-summary-mark-article nil gnus-unread-mark))))
-         (if  gnus-visual
-             (run-hooks 'gnus-visual-summary-update-hook))))))
+      (let ((gnus-summary-inhibit-highlight t))
+       (progn
+         (or dont-update
+             (if (and gnus-summary-mark-below
+                      (< (gnus-summary-article-score) gnus-summary-mark-below))
+                 (and (not (memq (gnus-summary-article-mark)
+                                 gnus-newsgroup-unreads))
+                      (gnus-summary-mark-article nil gnus-low-score-mark))
+               (and (eq (gnus-summary-article-mark) gnus-low-score-mark)
+                    (gnus-summary-mark-article nil gnus-unread-mark))))
+         (and gnus-visual
+              (run-hooks 'gnus-visual-summary-update-hook))))))
 
 (defun gnus-summary-update-lines ()
   ;; Rehighlight summary buffer according to `gnus-summary-highlight'.
-  (if (and gnus-visual gnus-visual-summary-update-hook)
-      (save-excursion
-       (set-buffer gnus-summary-buffer)
-       (goto-char (point-min))
-       (while (not (eobp))
-         (gnus-summary-update-line)
-         (forward-line 1)))))
+  (and (save-excursion
+        (set-buffer gnus-summary-buffer)
+        (goto-char (point-min))
+        (while (not (eobp))
+          (gnus-summary-update-line)
+          (forward-line 1)))))
 
 (defun gnus-summary-read-group (group &optional show-all no-article kill-buffer)
   "Start reading news in newsgroup GROUP.
@@ -4541,6 +4649,10 @@ If NO-ARTICLE is non-nil, no article is selected initially."
              ;; This newsgroup is empty.
              (gnus-summary-catchup-and-exit nil t) ;Without confirmations.
              (message "No unread news"))
+         (save-excursion
+           (if kill-buffer
+               (let ((gnus-summary-buffer kill-buffer))
+                 (gnus-configure-windows 'newsgroups t))))
          ;; Hide conversation thread subtrees.  We cannot do this in
          ;; gnus-summary-prepare-hook since kill processing may not
          ;; work with hidden articles.
@@ -4573,39 +4685,21 @@ If NO-ARTICLE is non-nil, no article is selected initially."
     (erase-buffer)
     (gnus-summary-prepare-threads 
      (if gnus-show-threads
-        (gnus-gather-threads (gnus-sort-threads (gnus-make-threads)))
+        (gnus-gather-threads 
+         (gnus-sort-threads 
+          (if gnus-summary-expunge-below
+              (gnus-make-threads-and-expunge)
+            (gnus-make-threads))))
        gnus-newsgroup-headers)
-     0)
-    (gnus-summary-remove-dormant-lines)
+     0 nil nil t)
     ;; Erase header retrieval message.
+    (gnus-summary-update-lines)
     (message "")
     ;; Call hooks for modifying summary buffer.
     ;; Suggested by sven@tde.LTH.Se (Sven Mattisson).
     (goto-char (point-min))
     (run-hooks 'gnus-summary-prepare-hook)))
 
-(defun gnus-summary-remove-dormant-lines ()
-  (let ((int gnus-newsgroup-dormant)
-       (buffer-read-only nil)
-       beg cur-level)
-    (while int
-      (if (gnus-summary-goto-subject (car int))
-         (progn
-           (beginning-of-line)
-           (setq cur-level (gnus-summary-thread-level))
-           (setq beg (point))
-           (re-search-forward "[\n\r]")
-           (if (<= (gnus-summary-thread-level) cur-level)
-               ;; If the level of the next article is greater than the
-               ;; level of this article, then it has to be the child of this
-               ;; article, so we do not delete this article.
-               (progn
-                 (setq gnus-newsgroup-dormant-subjects
-                       (cons (cons (car int) (buffer-substring beg (point)))
-                             gnus-newsgroup-dormant-subjects))
-                 (delete-region beg (point))))))
-      (setq int (cdr int)))))
-
 (defun gnus-gather-threads (threads)
   "Gather threads that have lost their roots."
   (if (not gnus-summary-make-false-root)
@@ -4669,11 +4763,111 @@ If NO-ARTICLE is non-nil, no article is selected initially."
                   (setq prev headers))
                 (setq headers (cdr headers)))))))
      gnus-newsgroup-dependencies)
-
-    (mapcar (lambda (root) (gnus-trim-thread (gnus-make-sub-thread root)))
-           roots)))
+    
+    (mapcar 'gnus-trim-thread
+           (apply 'append
+                  (mapcar 'gnus-cut-thread
+                          (mapcar 'gnus-make-sub-thread roots))))))
+  
+(defun gnus-make-threads-and-expunge ()
+  ;; This function takes the dependencies already made by 
+  ;; `gnus-get-newsgroup-headers' and builds the trees. First we go
+  ;; through the dependecies in the hash table and finds all the
+  ;; roots. Roots do not refer back to any valid articles.
+  (let (roots)
+    (and gnus-fetch-old-headers (eq gnus-headers-retrieved-by 'nov)
+        (gnus-build-old-threads))
+    (mapatoms
+     (lambda (refs)
+       (if (not (car (symbol-value refs)))
+          (if (and gnus-summary-expunge-below
+                   (not gnus-fetch-old-headers))
+              (let ((headers (cdr (symbol-value refs))))
+                (while headers
+                 (if (not (< (or (cdr (assq (header-number (car headers))
+                                            gnus-newsgroup-scored))
+                                 gnus-summary-default-score 0)
+                             gnus-summary-expunge-below))
+                     (setq roots (cons (car headers) roots))
+                   (setq gnus-newsgroup-unreads
+                         (delq (header-number (car headers))
+                               gnus-newsgroup-unreads)))
+                 (setq headers (cdr headers))))
+            (setq roots (append (cdr (symbol-value refs)) roots)))
+        ;; Ok, these refer back to valid articles, but if
+        ;; `gnus-thread-ignore-subject' is nil, we have to check that
+        ;; the root has the same subject as its children. The children
+        ;; that do not are made into roots and removed from the list
+        ;; of children. 
+        (or gnus-thread-ignore-subject
+            (let* ((prev (symbol-value refs))
+                   (subject (gnus-simplify-subject-re 
+                             (header-subject (car prev))))
+                   (headers (cdr prev)))
+              (while headers
+                (if (not (string= subject
+                                  (gnus-simplify-subject-re 
+                                   (header-subject (car headers)))))
+                    (progn
+                      (setq roots (cons (car headers) roots))
+                      (setcdr prev (cdr headers)))
+                  (setq prev headers))
+                (setq headers (cdr headers)))))
+        (and gnus-summary-expunge-below
+             (not gnus-fetch-old-headers)
+             (let* ((prev (symbol-value refs))
+                    (headers (cdr prev))
+                    id)
+               (while headers
+                 (if (not (< (or (cdr (assq (header-number (car headers))
+                                            gnus-newsgroup-scored))
+                                 gnus-summary-default-score 0)
+                             gnus-summary-expunge-below))
+                     (setq prev (cdr prev))
+                   (setq gnus-newsgroup-unreads 
+                         (delq (header-number (car headers))
+                               gnus-newsgroup-unreads))
+                   (setcdr prev (cdr headers))
+                   (setq id (gnus-gethash (header-id (car headers))
+                                          gnus-newsgroup-dependencies))
+                   (let ((h (cdr id)))
+                     (while h
+                       (if (not (< (or (cdr (assq (header-number (car h))
+                                                  gnus-newsgroup-scored))
+                                       gnus-summary-default-score 0)
+                                   gnus-summary-expunge-below))
+                           (setq roots (cons (car h) roots)))
+                       (setq h (cdr h)))))
+                 (setq headers (cdr headers)))))))
+     gnus-newsgroup-dependencies)
+    
+    (mapcar 'gnus-trim-thread
+           (apply 'append
+                  (mapcar 'gnus-cut-thread
+                          (mapcar 'gnus-make-sub-thread roots))))))
+  
+(defun gnus-cut-thread (thread)
+  ;; Remove leaf dormant or ancient articles from THREAD.
+  (let ((head (car thread))
+       (tail (apply 'append (mapcar 'gnus-cut-thread (cdr thread)))))
+    (if (and (null tail)
+            (let ((number (header-number head)))
+              (or (memq number gnus-newsgroup-ancient)
+                  (memq number gnus-newsgroup-dormant)
+                  (and gnus-summary-expunge-below
+                       (eq gnus-fetch-old-headers 'some)
+                       (< (or (cdr (assq number gnus-newsgroup-scored))
+                              gnus-summary-default-score 0)
+                          gnus-summary-expunge-below)
+                       (progn
+                         (setq gnus-newsgroup-unreads
+                               (delq number gnus-newsgroup-unreads))
+                         t)))))
+       nil
+      (list (cons head tail)))))
 
 (defun gnus-trim-thread (thread)
+  ;; Remove root ancient articles with only one child from THREAD.
   (if (and (eq gnus-fetch-old-headers 'some)
           (memq (header-number (car thread)) gnus-newsgroup-ancient)
           (= (length thread) 2))
@@ -4765,9 +4959,11 @@ If NO-ARTICLE is non-nil, no article is selected initially."
   (let ((h1 (gnus-thread-header h1))
        (h2 (gnus-thread-header h2)))
     (string-lessp
-     (let ((extract (gnus-extract-address-components (header-from h1))))
+     (let ((extract (funcall 
+                    gnus-extract-address-components (header-from h1))))
        (or (car extract) (cdr extract)))
-     (let ((extract (gnus-extract-address-components (header-from h2))))
+     (let ((extract (funcall
+                    gnus-extract-address-components (header-from h2))))
        (or (car extract) (cdr extract))))))
 
 (defun gnus-thread-sort-by-subject (h1 h2)
@@ -4822,11 +5018,10 @@ Unscored articles will be counted as havin a score of zero."
 
 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defvar gnus-tmp-prev-subject "")
-(defvar gnus-tmp-prev-dormant nil)
 
 ;; Basic ideas by Paul Dworkin <paul@media-lab.media.mit.edu>.
 (defun gnus-summary-prepare-threads 
-  (threads level &optional not-child no-subject)
+  (threads level &optional not-child no-subject cull)
   "Prepare summary buffer from THREADS and indentation LEVEL.  
 THREADS is either a list of `(PARENT [(CHILD1 [(GRANDCHILD ...]...) ...])'  
 or a straight list of headers."
@@ -4838,41 +5033,51 @@ or a straight list of headers."
       ;; `thread' is the header.
       (if (consp thread)
          (setq header (car thread))
-       (setq header thread))
-      (if (stringp header)
-         ;; The header is a dummy root.
-         (progn
-           (cond ((eq gnus-summary-make-false-root 'adopt)
-                  ;; We let the first article adopt the rest.
-                  (gnus-summary-prepare-threads (list (car (cdr thread))) 0)
-                  (setq thread (cdr (cdr thread)))
-                  (while thread
-                    (gnus-summary-prepare-threads (list (car thread)) 1 t)
-                    (setq thread (cdr thread))))
-                 ((eq gnus-summary-make-false-root 'dummy)
-                  ;; We output a dummy root.
-                  (gnus-summary-insert-dummy-line 
-                   nil header (header-number (car (car (cdr thread)))))
-                  (setq clevel 1))
-                 ((eq gnus-summary-make-false-root 'empty)
-                  ;; We print the articles with empty subject fields. 
-                  (gnus-summary-prepare-threads (list (car (cdr thread))) 0)
-                  (setq thread (cdr (cdr thread)))
-                  (while thread
-                    (gnus-summary-prepare-threads (list (car thread)) 0 nil
-                                                  (not gnus-tmp-prev-dormant))
-                    (setq thread (cdr thread))))
-                 (t
-                  ;; We do not make a root for the gathered
-                  ;; sub-threads at all.  
-                  (setq clevel 0)))
-           ;; Print the sub-threads.
-           (and (consp thread) (cdr thread)
-                (gnus-summary-prepare-threads (cdr thread) clevel)))
-       ;; The header is a real article.
+       (setq header thread)
+       (and cull
+            (or (memq (setq number (header-number header))
+                      gnus-newsgroup-dormant)
+                (and gnus-summary-expunge-below
+                     (< (or (cdr (assq number gnus-newsgroup-scored))
+                            gnus-summary-default-score 0)
+                        gnus-summary-expunge-below)))
+            (progn
+              (setq header nil)
+              (setq gnus-newsgroup-unreads 
+                    (delq number gnus-newsgroup-unreads)))))
+      (cond 
+       ((stringp header)
+       ;; The header is a dummy root.
+       (cond ((eq gnus-summary-make-false-root 'adopt)
+              ;; We let the first article adopt the rest.
+              (gnus-summary-prepare-threads (list (car (cdr thread))) 0)
+              (setq thread (cdr (cdr thread)))
+              (while thread
+                (gnus-summary-prepare-threads (list (car thread)) 1 t)
+                (setq thread (cdr thread))))
+             ((eq gnus-summary-make-false-root 'dummy)
+              ;; We output a dummy root.
+              (gnus-summary-insert-dummy-line 
+               nil header (header-number (car (car (cdr thread)))))
+              (setq clevel 1))
+             ((eq gnus-summary-make-false-root 'empty)
+              ;; We print the articles with empty subject fields. 
+              (gnus-summary-prepare-threads (list (car (cdr thread))) 0)
+              (setq thread (cdr (cdr thread)))
+              (while thread
+                (gnus-summary-prepare-threads (list (car thread)) 0 nil t)
+                (setq thread (cdr thread))))
+             (t
+              ;; We do not make a root for the gathered
+              ;; sub-threads at all.  
+              (setq clevel 0)))
+       ;; Print the sub-threads.
+       (and (consp thread) (cdr thread)
+            (gnus-summary-prepare-threads (cdr thread) clevel)))
+       ;; The header is a real article.
+       (header
        (setq number (header-number header)
-             subject (header-subject header)
-             gnus-tmp-prev-dormant (memq number gnus-newsgroup-dormant))
+             subject (header-subject header))
        (gnus-summary-insert-line
         nil header level nil 
         (cond ((memq number gnus-newsgroup-marked) gnus-ticked-mark)
@@ -4895,7 +5100,7 @@ or a straight list of headers."
        (setq gnus-tmp-prev-subject subject)
        ;; Recursively print subthreads.
        (and (consp thread) (cdr thread)
-            (gnus-summary-prepare-threads (cdr thread) (1+ level)))))))
+            (gnus-summary-prepare-threads (cdr thread) (1+ level))))))))
 
 (defun gnus-select-newsgroup (group &optional read-all)
   "Select newsgroup GROUP.
@@ -4907,24 +5112,16 @@ If READ-ALL is non-nil, all articles in the group are selected."
         (or (gnus-activate-newsgroup (car info))
             (progn
               (kill-buffer (current-buffer))
-              (error "Couldn't request newsgroup %s" group))))
+              (error "Couldn't request group %s: %s" 
+                     group (gnus-status-message group)))))
     (setq gnus-current-select-method (or (nth 4 info) gnus-select-method))
     (gnus-check-news-server (nth 4 info))
     (or (gnus-request-group group t)
        (progn
          (kill-buffer (current-buffer))
-         (error "Couldn't request newsgroup %s" group)))
+         (error "Couldn't request group %s: %s" 
+                group (gnus-status-message group))))
 
-    ;; Initialize the buffer that holds lines that have been removed
-    ;; from the summary buffer.
-    (save-excursion
-      (set-buffer
-       (setq gnus-newsgroup-expunged-buffer 
-            (get-buffer-create (format " *gnus expunge %s*" group))))
-      (buffer-disable-undo (current-buffer))
-      (erase-buffer)
-      (gnus-add-current-to-buffer-list))
-    
     (setq gnus-newsgroup-name group)
     (setq gnus-newsgroup-unselected nil)
     (setq gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
@@ -4968,7 +5165,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
           (setq gnus-newsgroup-headers (cdr gnus-newsgroup-headers)))
       ;; Remove cancelled articles from the list of unread articles.
       (setq gnus-newsgroup-unreads
-           (gnus-intersection 
+           (gnus-set-sorted-intersection 
             gnus-newsgroup-unreads
             (mapcar (lambda (headers) (header-number headers))
                     gnus-newsgroup-headers)))
@@ -4994,7 +5191,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
          ;; unread articles are dormant articles.
          (if (or read-all
                  (= (length gnus-newsgroup-unreads) 
-                    (length gnus-newsgroup-scored)))
+                    (length gnus-newsgroup-dormant)))
              (gnus-uncompress-sequence 
               (gnus-gethash group gnus-active-hashtb))
            gnus-newsgroup-unreads))
@@ -5020,13 +5217,14 @@ If READ-ALL is non-nil, all articles in the group are selected."
                     (let ((input
                            (read-string
                             (format 
-                             "%s %s (%d scored, %d total, %d default): "
+                             "%s %s (%d scored, %d total): "
                              "How many articles from"
-                             group scored number scored))))
+                             group scored number))))
                       (if (string-equal input "")
-                          scored input)))
+                          number input)))
                    (t number))
-           (quit 0))))
+           (quit 0)))
+        total-articles)
     (setq select (if (numberp select) select (string-to-number select)))
     (if (zerop select)
        ()
@@ -5036,6 +5234,8 @@ If READ-ALL is non-nil, all articles in the group are selected."
            (setq number (length articles)))
        (setq articles (copy-sequence articles)))
 
+      (setq total-articles articles)
+      
       (if (< (abs select) number)
          (if (< select 0) 
              ;; Select the N oldest articles.
@@ -5043,7 +5243,9 @@ 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-set-difference gnus-newsgroup-unreads articles))
+           (gnus-sorted-intersection
+            gnus-newsgroup-unselected 
+            (gnus-sorted-complement articles total-articles)))
       articles)))
 
 (defun gnus-killed-articles (killed articles)
@@ -5054,10 +5256,10 @@ If READ-ALL is non-nil, all articles in the group are selected."
       (setq articles (cdr articles)))
     out))
 
-(defun gnus-adjust-marked-articles (info)
+(defun gnus-adjust-marked-articles (info &optional active)
   "Remove all marked articles that are no longer legal."
   (let ((marked-lists (nth 3 info))
-       (active (gnus-gethash (car info) gnus-active-hashtb))
+       (active (or active (gnus-gethash (car info) gnus-active-hashtb)))
        marked m prev)
     ;; There are four types of marked articles - ticked, replied,
     ;; expirable and dormant.  
@@ -5176,15 +5378,20 @@ If WHERE is `summary', the summary mode line format will be used."
                 (article-number (or gnus-current-article 0))
                 (unread (- (length gnus-newsgroup-unreads)
                            (length gnus-newsgroup-dormant)))
+                (unread-and-unticked 
+                 (- unread (length gnus-newsgroup-marked)))
                 (unselected (length gnus-newsgroup-unselected))
                 (unread-and-unselected
-                 (cond ((and (zerop unread) (zerop unselected)) "")
-                       ((zerop unselected) (format "{%d more}" unread))
-                       (t (format "{%d(+%d) more}" unread unselected))))
+                 (cond ((and (zerop unread-and-unticked)
+                             (zerop unselected)) "")
+                       ((zerop unselected) 
+                        (format "{%d more}" unread-and-unticked))
+                       (t (format "{%d(+%d) more}"
+                                  unread-and-unticked unselected))))
                 (subject
                  (if gnus-current-headers
                      (header-subject gnus-current-headers) ""))
-                (max-len (if (eq where 'summary) 59 59)))
+                (max-len (- (frame-width) gnus-mode-non-string-length)))
            (setq mode-string (eval mformat))
            (if (> (length mode-string) max-len) 
                (setq mode-string 
@@ -5227,87 +5434,105 @@ The resulting hash table is returned, or nil if no Xrefs were found."
 
 (defun gnus-mark-xrefs-as-read (from-newsgroup headers unreads expirable)
   "Look through all the headers and mark the Xrefs as read."
-  (let (name entry read info xref-hashtb idlist active num range exps method)
-    (set-buffer gnus-group-buffer)
-    (if (setq xref-hashtb 
-             (gnus-create-xref-hashtb from-newsgroup headers unreads))
-       (mapatoms 
-        (lambda (group)
-          (if (string= from-newsgroup (setq name (symbol-name group)))
-              ()
-            (setq idlist (symbol-value group))
-            ;; Dead groups are not updated.
-            (if (and (setq entry (gnus-gethash name gnus-newsrc-hashtb))
-                     ;; Only do the xrefs if the group has the same
-                     ;; select method as the group we have just read.
-                     (or (and (not (nth 4 (setq info (nth 2 entry))))
-                              (eq (gnus-find-method-for-group from-newsgroup)
-                                  gnus-select-method))
-                         (memq 'virtual 
-                               (assoc (symbol-name 
-                                       (car (gnus-find-method-for-group 
-                                             from-newsgroup)))
-                                      gnus-valid-select-methods))
-                         (equal (nth 4 info) 
-                                (setq method (gnus-find-method-for-group 
-                                              from-newsgroup)))
-                         (and (equal (car (nth 4 info)) (car method))
-                              (equal (nth 1 (nth 4 info)) (nth 1 method))))
-                     gnus-use-cross-reference
-                     (or (not (eq gnus-use-cross-reference t))
-                         (<= (nth 1 info) 5)))
-                (progn
-                  (setq num 0)
-                  ;; Set the new list of read articles in this group.
-                  (setq active (gnus-gethash name gnus-active-hashtb))
-                  ;; First peel off all illegal article numbers.
-                  (if active
-                      (let ((ids idlist)
-                            (ticked (cdr (memq 'tick (nth 3 info))))
-                            (dormant (cdr (memq 'dormant (nth 3 info))))
-                            id)
-                        (setq exps nil)
-                        (while ids
-                          (setq id (car ids))
-                          (if (or (> id (cdr active))
-                                  (< id (car active))
-                                  (memq id ticked)
-                                  (memq id dormant))
-                              (setq idlist (delq id idlist)))
-                          (and (memq id expirable)
-                               (setq exps (cons id exps)))
-                          (setq ids (cdr ids)))))
-                  ;; Update expirable articles.
-                  (gnus-add-marked-articles nil 'expirable exps info)
-                  (setcar (nthcdr 2 info)
-                          (setq range
-                                (gnus-add-to-range 
-                                 (nth 2 info) 
-                                 (setq idlist (sort idlist '<)))))
-                  ;; Then we have to re-compute how many unread
-                  ;; articles there are in this group.
-                  (if active
-                      (progn
-                        (if (atom (car range))
-                            (if (not range)
-                                (setq num (- (1+ (cdr active)) (car active)))
-                              (setq num (- (cdr active) (- (1+ (cdr range)) 
-                                                           (car range)))))
-                          (while range
-                            (setq num (+ num (- (1+ (cdr (car range))) 
-                                                (car (car range)))))
-                            (setq range (cdr range)))
-                          (setq num (- (cdr active) num)))
-                        ;; Update the number of unread articles.
-                        (setcar 
-                         entry 
-                         (max 0 (- num (length 
-                                        (cdr (memq 'tick (nth 3 info))) )
-                                   (length (cdr (memq 'dormant 
-                                                      (nth 3 info)))))))
-                        ;; Update the group buffer.
-                        (gnus-group-update-group name t)))))))
-        xref-hashtb))))
+  (let ((virtual (memq 'virtual 
+                      (assoc (symbol-name (car (gnus-find-method-for-group 
+                                                from-newsgroup)))
+                             gnus-valid-select-methods)))
+       name entry read info xref-hashtb idlist active num range exps method)
+    (save-excursion
+      (set-buffer gnus-group-buffer)
+      (if (setq xref-hashtb 
+               (gnus-create-xref-hashtb from-newsgroup headers unreads))
+         (mapatoms 
+          (lambda (group)
+            (if (string= from-newsgroup (setq name (symbol-name group)))
+                ()
+              (setq idlist (symbol-value group))
+              ;; Dead groups are not updated.
+              (if (and (setq entry (gnus-gethash name gnus-newsrc-hashtb)
+                             info (nth 2 entry))
+                       ;; Only do the xrefs if the group has the same
+                       ;; select method as the group we have just read.
+                       (or (gnus-methods-equal-p 
+                            (nth 4 info)
+                            (gnus-find-method-for-group from-newsgroup))
+                           virtual
+                           (equal (nth 4 info) 
+                                  (setq method (gnus-find-method-for-group 
+                                                from-newsgroup)))
+                           (and (equal (car (nth 4 info)) (car method))
+                                (equal (nth 1 (nth 4 info)) (nth 1 method))))
+                       gnus-use-cross-reference
+                       (or (not (eq gnus-use-cross-reference t))
+                           virtual
+                           ;; Only do cross-references on subscribed
+                           ;; groups, if that is what is wanted.  
+                           (<= (nth 1 info) 5)))
+                  (progn
+                    (setq num 0)
+                    ;; Set the new list of read articles in this group.
+                    (setq active (gnus-gethash name gnus-active-hashtb))
+                    ;; First peel off all illegal article numbers.
+                    (if active
+                        (let ((ids idlist)
+                              (ticked (cdr (assq 'tick (nth 3 info))))
+                              (dormant (cdr (assq 'dormant (nth 3 info))))
+                              id)
+                          (setq exps nil)
+                          (while ids
+                            (setq id (car ids))
+                            (if (or (> id (cdr active))
+                                    (< id (car active))
+                                    (memq id ticked)
+                                    (memq id dormant))
+                                (setq idlist (delq id idlist)))
+                            (and (memq id expirable)
+                                 (setq exps (cons id exps)))
+                            (setq ids (cdr ids)))))
+                    ;; Update expirable articles.
+                    (gnus-add-marked-articles nil 'expirable exps info)
+                    (and (null (nth 2 info))
+                         (> (car active) 1)
+                         (setcar (nthcdr 2 info) (cons 1 (1- (car active)))))
+                    (setcar (nthcdr 2 info)
+                            (setq range
+                                  (gnus-add-to-range 
+                                   (nth 2 info) 
+                                   (setq idlist (sort idlist '<)))))
+                    ;; Then we have to re-compute how many unread
+                    ;; articles there are in this group.
+                    (if active
+                        (progn
+                          (if (atom (car range))
+                              (if (not range)
+                                  (setq num (- (1+ (cdr active)) 
+                                               (car active)))
+                                (setq num (- (cdr active) (- (1+ (cdr range)) 
+                                                             (car range)))))
+                            (while range
+                              (setq num (+ num (- (1+ (cdr (car range))) 
+                                                  (car (car range)))))
+                              (setq range (cdr range)))
+                            (setq num (- (cdr active) num)))
+                          ;; Update the number of unread articles.
+                          (setcar 
+                           entry 
+                           (max 0 (- num 
+                                     (length (cdr (assq 'tick (nth 3 info))))
+                                     (length 
+                                      (cdr (assq 'dormant (nth 3 info)))))))
+                          ;; Update the group buffer.
+                          (gnus-group-update-group name t)))))))
+          xref-hashtb)))))
+
+(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)))))))
 
 (defsubst gnus-header-value ()
   (buffer-substring (match-end 0) (save-excursion (end-of-line) (point))))
@@ -5603,16 +5828,19 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
       (setq header (gnus-read-header artnum)))
     header))
 
-(defun gnus-more-header-forward ()
-  "Find new header forward."
-  (let ((last (cdr (gnus-gethash gnus-newsgroup-name gnus-active-hashtb)))
-       (artnum gnus-newsgroup-end)
-       (header nil))
-    (while (and (not header)
-               (< artnum last))
-      (setq artnum (1+ artnum))
-      (setq header (gnus-read-header artnum)))
-    header))
+(defun gnus-more-header-forward (&optional backward)
+  "Find new header forward.
+If BACKWARD, find new header backward instead."
+  (if backward
+      (gnus-more-header-backward)
+    (let ((last (cdr (gnus-gethash gnus-newsgroup-name gnus-active-hashtb)))
+         (artnum gnus-newsgroup-end)
+         (header nil))
+      (while (and (not header)
+                 (< artnum last))
+       (setq artnum (1+ artnum))
+       (setq header (gnus-read-header artnum)))
+      header)))
 
 (defun gnus-extend-newsgroup (header &optional backward)
   "Extend newsgroup selection with HEADER.
@@ -5748,22 +5976,28 @@ article number."
 (defun gnus-summary-article-score ()
   "Return current article score."
   (or (cdr (assq (gnus-summary-article-number) gnus-newsgroup-scored))
-      gnus-summary-default-score))
+      gnus-summary-default-score 0))
 
 (defun gnus-summary-recenter ()
-  "Center point in summary window."
+  "Center point in the summary window.
+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 ((half (/ (- (window-height) 2) 2)))
+  (let ((top (cond ((< (window-height) 4) 0)
+                  ((< (window-height) 6) 1)
+                  (t 2))))
     (and 
-     ;; It has to be wanted,
+     ;; The user has to want it,
      gnus-auto-center-summary 
      ;; the article buffer must be displayed,
      (get-buffer-window gnus-article-buffer)
      ;; there must be lines left to scroll forward,
-     (zerop (save-excursion (forward-line (1+ half))))
+     (zerop (save-excursion (forward-line (- (window-height) 1 top))))
      ;; so we recenter.
-     (recenter half))))
+     (set-window-start 
+      (get-buffer-window (current-buffer)) 
+      (save-excursion (forward-line (- top)) (point))))))
 
 (defun gnus-summary-jump-to-group (newsgroup)
   "Move point to NEWSGROUP in group mode buffer."
@@ -5852,8 +6086,7 @@ Prefix argument SHOW-ALL means to select all articles."
     ;; exiting.
     (gnus-summary-jump-to-group gnus-newsgroup-name)
     (gnus-group-read-group show-all t)
-    (gnus-summary-goto-subject current-subject)
-    ))
+    (gnus-summary-goto-subject current-subject)))
 
 (defun gnus-summary-rescan-group (all)
   "Exit the newsgroup, ask for new articles, and select the newsgroup."
@@ -5885,7 +6118,7 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
        (setq gnus-newsgroup-killed
              (gnus-compress-sequence
               (nconc
-               (gnus-intersection
+               (gnus-set-sorted-intersection
                 (gnus-uncompress-sequence gnus-newsgroup-killed)
                 (setq gnus-newsgroup-unselected
                       (sort gnus-newsgroup-unselected '<)))
@@ -5898,16 +6131,12 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
       (gnus-close-group group)
       (run-hooks 'gnus-exit-group-hook)
       (gnus-score-save)
-      (and gnus-newsgroup-expunged-buffer 
-          (buffer-name gnus-newsgroup-expunged-buffer)
-          (kill-buffer gnus-newsgroup-expunged-buffer))
       (gnus-update-read-articles 
        group gnus-newsgroup-unreads gnus-newsgroup-unselected 
        gnus-newsgroup-marked
        t gnus-newsgroup-replied gnus-newsgroup-expirable
        gnus-newsgroup-killed gnus-newsgroup-dormant
        gnus-newsgroup-bookmarks gnus-newsgroup-scored)
-      ;; t means ignore unsubscribed newsgroups.
       (and gnus-use-cross-reference
           (gnus-mark-xrefs-as-read 
            group headers gnus-newsgroup-unreads gnus-newsgroup-expirable))
@@ -5924,8 +6153,18 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
        ;; If exiting temporary, caller should adjust group mode
        ;; buffer point by itself.
        nil                             ;Nothing to do.
-      ;; Return to group mode buffer. 
+      ;; 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.
+      (set-buffer buf)
+      (gnus-summary-clear-local-variables)
+      ;; 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)
       (gnus-configure-windows 'newsgroups t)
+      ;; Return to group mode buffer. 
       (and (get-buffer buf) 
           (eq mode 'gnus-summary-mode)
           (kill-buffer buf))
@@ -5942,36 +6181,44 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
 (defun gnus-summary-quit (&optional no-questions)
   "Quit reading current newsgroup without updating read article info."
   (interactive)
-  (let ((group gnus-newsgroup-name)
-       (quit-buffer (cdr (assoc 'quit-buffer (gnus-find-method-for-group
-                                              gnus-newsgroup-name)))))
+  (let* ((group gnus-newsgroup-name)
+        (quit-buffer (cdr (assoc 'quit-buffer 
+                                 (gnus-find-method-for-group group)))))
     (if (or no-questions
            gnus-expert-user
            (gnus-y-or-n-p "Do you really wanna quit reading this group? "))
        (progn
          (gnus-close-group group)
+         (gnus-summary-clear-local-variables)
+         (set-buffer gnus-group-buffer)
+         (gnus-summary-clear-local-variables)
          ;; Return to group selection mode.
-         (and gnus-newsgroup-expunged-buffer 
-              (buffer-name gnus-newsgroup-expunged-buffer)
-              (kill-buffer gnus-newsgroup-expunged-buffer))
          (gnus-configure-windows 'newsgroups)
          (if (get-buffer gnus-summary-buffer)
              (kill-buffer gnus-summary-buffer))
          (if (get-buffer gnus-article-buffer)
              (bury-buffer gnus-article-buffer))
          (pop-to-buffer gnus-group-buffer)
-         (gnus-group-jump-to-group gnus-newsgroup-name)
+         (gnus-group-jump-to-group group)
          (gnus-group-next-group 1)
          (if (and quit-buffer (buffer-name quit-buffer))
              (progn
                (switch-to-buffer quit-buffer)
                (gnus-configure-windows 'summary)))))))
 
+;; Suggested by Andrew Eskilsson <pi92ae@pt.hk-r.se>.
+(defun gnus-summary-fetch-faq (group)
+  "Fetch the FAQ for the current group."
+  (interactive (list gnus-newsgroup-name))
+  (gnus-configure-windows 'article)
+  (pop-to-buffer gnus-article-buffer)
+  (find-file (concat gnus-group-faq-directory group)))
+
 ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-summary-describe-group ()
+(defun gnus-summary-describe-group (force)
   "Describe the current newsgroup."
-  (interactive)
-  (gnus-group-describe-group gnus-newsgroup-name))
+  (interactive "P")
+  (gnus-group-describe-group force gnus-newsgroup-name))
 
 (defun gnus-summary-describe-briefly ()
   "Describe summary mode commands briefly."
@@ -5981,16 +6228,26 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
 
 ;; Walking around group mode buffer from summary mode.
 
-(defun gnus-summary-next-group (&optional no-article group)
+(defun gnus-summary-next-group (&optional no-article 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 prefix argument NO-ARTICLE is non-nil, no article is selected initially.
+If BACKWARD, go to previous group instead."
   (interactive "P")
   (gnus-set-global-variables)
   (let ((ingroup gnus-newsgroup-name)
-       (sumbuf (current-buffer)))
+       (sumbuf (current-buffer))
+       num)
     (gnus-summary-exit t)              ;Update all information.
-    (gnus-group-jump-to-group ingroup)
-    (let ((group (or group (gnus-summary-search-group)))
+    (if (and group
+            (or (and (numberp (setq num (car (gnus-gethash
+                                              group gnus-newsrc-hashtb))))
+                     (< num 1))
+                (null num)))
+       (progn
+         (gnus-group-jump-to-group group)
+         (setq group nil))
+      (gnus-group-jump-to-group ingroup))
+    (let ((group (or group (gnus-summary-search-group backward)))
          (buf gnus-summary-buffer))
       (if (null group)
          (gnus-summary-quit t)
@@ -6009,34 +6266,7 @@ If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
   "Exit current newsgroup and then select previous unread newsgroup.
 If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
   (interactive "P")
-  ;; Make sure group mode buffer point is on current newsgroup.
-  (gnus-summary-jump-to-group gnus-newsgroup-name)
-  (let ((group (gnus-summary-search-group t)))
-    (if (null group)
-       (progn
-         (message "Exiting %s..." gnus-newsgroup-name)  
-         (gnus-summary-exit)
-         (message ""))
-      (message "Selecting %s..." group)
-      (gnus-summary-exit t)            ;Exit summary mode temporary.
-      ;; We are now in group mode buffer.
-      ;; We have to adjust point of group mode buffer because current
-      ;; point is moved to next unread newsgroup by exiting.
-      (gnus-summary-jump-to-group group)
-      (gnus-summary-read-group group nil no-article)
-      (or (eq (current-buffer)
-             (get-buffer gnus-summary-buffer))
-         (eq gnus-auto-select-next t)
-         ;; Expected newsgroup has nothing to read since the articles
-         ;; are marked as read by cross-referencing. So, try next
-         ;; newsgroup. (Make sure we are in group mode buffer now.)
-         (and (eq (current-buffer)
-                  (get-buffer gnus-group-buffer))
-              (gnus-summary-search-group t)
-              (gnus-summary-read-group
-               (gnus-summary-search-group t) nil no-article))
-         )
-      )))
+  (gnus-summary-next-group no-article nil t))
 
 ;; Walking around summary lines.
 
@@ -6044,6 +6274,7 @@ If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
   "Go to the first unread subject.
 If UNREAD is non-nil, go to the first unread article.
 Returns nil if there are no unread articles."
+  (interactive "P")
   (let ((begin (point)))
     (if unread
        (if (not (gnus-goto-char 
@@ -6131,9 +6362,10 @@ If optional argument UNREAD is non-nil, only unread article is selected."
     (run-hooks 'gnus-select-article-hook)
     (gnus-summary-recenter)
 ;    (set-window-point (get-buffer-window (current-buffer)) (point-max))
-    (sit-for 0)
+;    (sit-for 0)
     (gnus-summary-goto-subject article)
     ;; Successfully display article.
+    (gnus-summary-update-line)
     t))
 
 (defun gnus-summary-select-article (&optional all-headers force pseudo)
@@ -6164,212 +6396,97 @@ be displayed."
   "Obsolete function."
   nil)
 
-(defun gnus-summary-next-article (unread &optional subject)
-  "Select the article after the current one.
-If UNREAD is non-nil, only unread articles are selected."
+(defun gnus-summary-next-article (unread &optional subject backward)
+  "Select the next article.
+If UNREAD, only unread articles are selected.
+If SUBJECT, only articles with SUBJECT are selected.
+If BACKWARD, the previous article is selected instead of the next."
   (interactive "P")
-  (let ((header nil)
-       (method (car (gnus-find-method-for-group gnus-newsgroup-name))))
-    (cond ((gnus-summary-display-article
-           (gnus-summary-search-forward unread subject)))
-         ((and subject
-               gnus-auto-select-same
-               (gnus-set-difference gnus-newsgroup-unreads
-                                    (append gnus-newsgroup-marked
-                                            gnus-newsgroup-dormant))
-               (memq this-command
-                     '(gnus-summary-next-unread-article
-                       gnus-summary-next-page
-                       gnus-summary-kill-same-subject-and-select
-                       ;;gnus-summary-next-article
-                       ;;gnus-summary-next-same-subject
-                       ;;gnus-summary-next-unread-same-subject
-                       )))
-          ;; Wrap article pointer if there are unread articles.
-          (let ((buffer (current-buffer))
-                (last-point (point)))
-            ;; No more articles with same subject, so jump to the first
-            ;; unread article.
-            (gnus-summary-first-unread-article)
-            ;;(and (eq buffer (current-buffer))
-            ;; (= (point) last-point)
-            ;; ;; Ignore given SUBJECT, and try again.
-            ;; (gnus-summary-next-article unread nil))
-            (and (eq buffer (current-buffer))
-                 (< (point) last-point)
-                 (message "Wrapped"))
-            ))
-         ((and gnus-auto-extend-newsgroup
-               (not unread)            ;Not unread only
-               (not subject)           ;Only if subject is not specified.
-               (setq header (gnus-more-header-forward)))
-          ;; Extend to next article if possible.
-          ;; Basic ideas by himacdonald@watdragon.waterloo.edu
-          (gnus-extend-newsgroup header nil)
-          ;; Threads feature must be turned off.
-          (let ((buffer-read-only nil))
-            (goto-char (point-max))
-            (gnus-summary-prepare-threads (list header) 0))
-          (gnus-summary-goto-article gnus-newsgroup-end))
-         (t
-          ;; Select next newsgroup automatically if requested.
-          (gnus-summary-jump-to-group gnus-newsgroup-name)
-          (let ((cmd (aref (this-command-keys) 0))
-                (group (if (eq gnus-keep-same-level 'best)
-                           (gnus-summary-best-group)
-                         (gnus-summary-search-group 
-                          nil gnus-keep-same-level)))
-                (auto-select
-                 (and gnus-auto-select-next
-                      ;;(null (gnus-set-difference gnus-newsgroup-unreads
-                      ;;                               gnus-newsgroup-marked))
-                      (memq this-command
-                            '(gnus-summary-next-unread-article
-                              gnus-summary-next-article
-                              gnus-summary-next-page
-                              gnus-summary-next-same-subject
-                              gnus-summary-next-unread-same-subject
-                              gnus-summary-kill-same-subject
-                              gnus-summary-kill-same-subject-and-select
-                              ))
-                      ;; Ignore characters typed ahead.
-                      (not (input-pending-p))
-                      )))
-            ;; Keep just the event type of CMD.
-            (if (listp cmd)
-                (setq cmd (car cmd)))
-            (message "No more%s articles%s"
-                     (if unread " unread" "")
-                     (if (and auto-select
-                              (not (eq gnus-auto-select-next 'quietly)))
-                         (if (and group (not (eq method 'nndigest)))
-                             (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))
-                       ""))
-            ;; Select next unread newsgroup automagically.
-            (cond ((and auto-select
-                        (eq gnus-auto-select-next 'quietly))
-                   ;; Select quietly.
-                   (if (eq method 'nndigest)
-                       (gnus-summary-exit)
-                     (gnus-summary-next-group)))
-                  (auto-select
-                   ;; Confirm auto selection.
-                   (let* ((event (read-event))
-                          (type
-                           (if (listp event)
-                               (car event)
-                             event)))
-                     (if (and (eq event type) (eq event cmd))
-                         (if (eq method 'nndigest)
-                             (gnus-summary-exit)
-                           (gnus-summary-next-group))
-                       (setq unread-command-events (list event)))))
-                  )
-            ))
-         )))
+  (let ((opoint (point))
+       (method (car (gnus-find-method-for-group gnus-newsgroup-name)))
+       header)
+    (cond
+     ;; Is there such an article?
+     ((gnus-summary-display-article 
+       (gnus-summary-search-forward unread subject backward))
+      (gnus-summary-position-cursor))
+     ;; If not, we try the first unread, if that is wanted.
+     ((and subject
+          gnus-auto-select-same
+          (gnus-summary-first-unread-article))
+      (message "Wrapped"))
+     ;; Try to get next/previous article not displayed in this group.
+     ((and gnus-auto-extend-newsgroup
+          (not unread) (not subject)
+          (setq header (gnus-more-header-forward backward)))
+      (gnus-extend-newsgroup header backward)
+      (let ((buffer-read-only nil))
+       (goto-char (if backward (point-min) (point-max)))
+       (gnus-summary-prepare-threads (list header) 0))
+      (gnus-summary-goto-article (if backward gnus-newsgroup-begin
+                                  gnus-newsgroup-end)))
+     ;; Go to next/previous group.
+     (t
+      (gnus-summary-jump-to-group gnus-newsgroup-name)
+      (let ((cmd (aref (this-command-keys) 0))
+           (group 
+            (if (eq gnus-keep-same-level 'best) (gnus-summary-best-group)
+              (gnus-summary-search-group backward gnus-keep-same-level))))
+       ;; Keep just the event type of CMD.
+       (and (listp cmd) (setq cmd (car cmd)))
+       ;; Select next unread newsgroup automagically.
+       (cond 
+        ((not gnus-auto-select-next)
+         (message "No more%s articles" (if unread " unread" "")))
+        ((eq gnus-auto-select-next 'quietly)
+         ;; Select quietly.
+         (if (eq method 'nndigest)
+             (gnus-summary-exit)
+           (message "No more%s articles (%s)..."
+                    (if unread " unread" "") 
+                    (if group (concat "selecting " group)
+                      "exiting"))
+           (gnus-summary-next-group nil group backward)))
+        (t
+         (let ((keystrokes '(?\C-n ?\C-p))
+               key)
+           (while (or (null key) (memq key keystrokes))
+             (message 
+              "No more%s articles%s" (if unread " unread" "")
+              (if (and group (not (eq method 'nndigest)))
+                  (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.
+             (let* ((event (read-event)))
+               (setq key (if (listp event) (car event) event))
+               (if (member key keystrokes)
+                   (let ((obuf (current-buffer)))
+                     (switch-to-buffer gnus-group-buffer)
+                     (gnus-group-jump-to-group group)
+                     (execute-kbd-macro (char-to-string key))
+                     (setq group (gnus-group-group-name))
+                     (switch-to-buffer obuf)))))
+           (if (eq key cmd)
+               (if (or (not group) (eq method 'nndigest))
+                   (gnus-summary-exit)
+                 (gnus-summary-next-group nil group backward))
+             (setq unread-command-events (list key)))))))))))
 
 (defun gnus-summary-next-unread-article ()
   "Select unread article after current one."
   (interactive)
   (gnus-summary-next-article t (and gnus-auto-select-same
-                                   (gnus-summary-subject-string)))
-  (gnus-summary-position-cursor))
+                                   (gnus-summary-subject-string))))
 
 (defun gnus-summary-prev-article (unread &optional subject)
   "Select the article after the current one.
 If UNREAD is non-nil, only unread articles are selected."
   (interactive "P")
-  (let ((header nil))
-    (cond ((gnus-summary-display-article
-           (gnus-summary-search-backward unread subject)))
-         ((and subject
-               gnus-auto-select-same
-               (gnus-set-difference gnus-newsgroup-unreads
-                                    (append gnus-newsgroup-marked
-                                            gnus-newsgroup-dormant))
-               (memq this-command
-                     '(gnus-summary-prev-unread-article
-                       gnus-summary-prev-page)))
-          ;; Wrap article pointer if there are unread articles.
-          (let ((buffer (current-buffer))
-                (last-point (point)))
-            ;; No more articles with same subject, so jump to the first
-            ;; unread article.
-            (gnus-summary-first-unread-article)
-            (and (eq buffer (current-buffer))
-                 (< (point) last-point)
-                 (message "Wrapped"))
-            ))
-         ((and gnus-auto-extend-newsgroup
-               (not unread)            ;Not unread only
-               (not subject)           ;Only if subject is not specified.
-               (setq header (gnus-more-header-backward)))
-          ;; Extend to next article if possible.
-          ;; Basic ideas by himacdonald@watdragon.waterloo.edu
-          (gnus-extend-newsgroup header t)
-          ;; Threads feature must be turned off.
-          (let ((buffer-read-only nil))
-            (goto-char (point-min))
-            (gnus-summary-prepare-threads (list header) 0))
-          (gnus-summary-goto-article gnus-newsgroup-begin))
-         (t
-          ;; Select prev newsgroup automatically if requested.
-          (gnus-summary-jump-to-group gnus-newsgroup-name)
-          (let ((cmd (aref (this-command-keys) 0))
-                (group (if (eq gnus-keep-same-level 'best)
-                           (gnus-summary-best-group)
-                         (gnus-summary-search-group 
-                          t gnus-keep-same-level)))
-                (auto-select
-                 (and gnus-auto-select-next
-                      (memq this-command
-                            '(gnus-summary-prev-unread-article
-                              gnus-summary-prev-article
-                              gnus-summary-prev-page))
-                      ;; Ignore characters typed ahead.
-                      (not (input-pending-p)))))
-            ;; Keep just the event type of CMD.
-            (if (listp cmd)
-                (setq cmd (car cmd)))
-            (message "No more%s articles%s"
-                     (if unread " unread" "")
-                     (if (and auto-select
-                              (not (eq gnus-auto-select-next 'quietly)))
-                         (if group
-                             (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))
-                       ""))
-            ;; Select next unread newsgroup automagically.
-            (cond ((and auto-select
-                        (eq gnus-auto-select-next 'quietly))
-                   ;; Select quietly.
-                   (gnus-summary-prev-group 1))
-                  (auto-select
-                   ;; Confirm auto selection.
-                   (let* ((event (read-event))
-                          (type
-                           (if (listp event)
-                               (car event)
-                             event)))
-                     (if (and (eq event type) (eq event cmd))
-                         (gnus-summary-prev-group 1)
-                       (setq unread-command-events (list event)))))
-                  )
-            ))
-         )))
+  (gnus-summary-next-article unread subject t))
 
 (defun gnus-summary-prev-unread-article ()
   "Select unred article before current one."
@@ -6512,6 +6629,18 @@ If ALL-HEADERS is non-nil, no header lines are hidden."
       (gnus-summary-goto-article gnus-last-article))
   (gnus-summary-position-cursor))
 
+(defun gnus-summary-pop-article (number)
+  "Pop one article off the history and go to the previous.
+NUMBER articles will be popped off."
+  (interactive "p")
+  (let (to)
+    (setq gnus-newsgroup-history
+         (cdr (setq to (nthcdr number gnus-newsgroup-history))))
+    (if to
+       (gnus-summary-goto-article (car to))
+      (error "Article history empty")))
+  (gnus-summary-position-cursor))
+
 ;; Summary article oriented commands
 
 (defun gnus-summary-refer-parent-article (n)
@@ -6546,20 +6675,23 @@ NOTE: This command only works with newsgroup that use NNTP."
        (setq message-id (concat "<" message-id)))
     (or (string-match ">$" message-id)
        (setq message-id (concat message-id ">")))
-    (let ((header (car (gnus-gethash message-id gnus-newsgroup-dependencies))))
+    (let ((header (car (gnus-gethash (downcase message-id)
+                                    gnus-newsgroup-dependencies))))
       (if header
          (gnus-summary-goto-article (header-number header))
-       (if (gnus-article-prepare message-id nil (gnus-read-header message-id))
-           (progn
-             (gnus-summary-insert-line 
-              nil gnus-current-headers 0 nil gnus-read-mark nil nil 
-              (header-subject gnus-current-headers))
-             (forward-line -1)
-             (gnus-summary-position-cursor)
-             (gnus-summary-update-line)
-             message-id)
-         (message "No such references")
-         nil)))))
+       (let ((gnus-override-method gnus-refer-article-method))
+         (if (gnus-article-prepare 
+              message-id nil (gnus-read-header message-id))
+             (progn
+               (gnus-summary-insert-line 
+                nil gnus-current-headers 0 nil gnus-read-mark nil nil 
+                (header-subject gnus-current-headers))
+               (forward-line -1)
+               (gnus-summary-position-cursor)
+               (gnus-summary-update-line)
+               message-id)
+           (message "No such references")
+           nil))))))
 
 (defun gnus-summary-enter-digest-group ()
   "Enter a digest group based on the current article."
@@ -6598,12 +6730,10 @@ gnus-select-article-hook is not called during the search."
       (setq regexp (or gnus-last-search-regexp ""))
     (setq gnus-last-search-regexp regexp))
   (if (gnus-summary-search-article regexp nil)
-      (gnus-eval-in-buffer-window gnus-article-buffer
-       (recenter 0)
-       ;;(sit-for 1)
-       )
-    (error "Search failed: \"%s\"" regexp)
-    ))
+      (gnus-eval-in-buffer-window 
+       gnus-article-buffer
+       (recenter 0))
+    (error "Search failed: \"%s\"" regexp)))
 
 (defun gnus-summary-search-article-backward (regexp)
   "Search for an article containing REGEXP backward.
@@ -6617,12 +6747,10 @@ gnus-select-article-hook is not called during the search."
       (setq regexp (or gnus-last-search-regexp ""))
     (setq gnus-last-search-regexp regexp))
   (if (gnus-summary-search-article regexp t)
-      (gnus-eval-in-buffer-window gnus-article-buffer
-       (recenter 0)
-       ;;(sit-for 1)
-       )
-    (error "Search failed: \"%s\"" regexp)
-    ))
+      (gnus-eval-in-buffer-window
+       gnus-article-buffer
+       (recenter 0))
+    (error "Search failed: \"%s\"" regexp)))
 
 (defun gnus-summary-search-article (regexp &optional backward)
   "Search for an article containing REGEXP.
@@ -6658,15 +6786,13 @@ gnus-select-article-hook is not called during the search."
        (save-restriction
          (widen)
          (goto-char (if backward (point-max) (point-min)))
-         (setq found (funcall re-search regexp nil t)))
-       ))
+         (setq found (funcall re-search regexp nil t)))))
     (message "")
     ;; Adjust article pointer.
     (or (eq last gnus-current-article)
        (setq gnus-last-article last))
     ;; Return T if found such article.
-    found
-    ))
+    found))
 
 (defun gnus-summary-execute-command (field regexp command &optional backward)
   "If FIELD of article header matches REGEXP, execute a COMMAND string.
@@ -6676,7 +6802,7 @@ If optional (prefix) argument BACKWARD is non-nil, do backward instead."
    (list (let ((completion-ignore-case t))
           (completing-read "Field name: "
                            '(("Number")("Subject")("From")
-                             ("Lines")("Date")("Id")
+                             ("Lines")("Date")("Message-ID")
                              ("Xref")("References"))
                            nil 'require-match))
         (read-string "Regexp: ")
@@ -6699,23 +6825,21 @@ If optional (prefix) argument BACKWARD is non-nil, do backward instead."
   "Scroll the article back to the beginning."
   (interactive)
   (gnus-summary-select-article)
-  (gnus-eval-in-buffer-window gnus-article-buffer
-    (widen)
-    (goto-char (point-min))
-    (if gnus-break-pages
-       (gnus-narrow-to-page))
-    ))
+  (gnus-eval-in-buffer-window
+   gnus-article-buffer
+   (widen)
+   (goto-char (point-min))
+   (and gnus-break-pages (gnus-narrow-to-page))))
 
 (defun gnus-summary-end-of-article ()
   "Scroll to the end of the article."
   (interactive)
   (gnus-summary-select-article)
-  (gnus-eval-in-buffer-window gnus-article-buffer
-    (widen)
-    (goto-char (point-max))
-    (if gnus-break-pages
-       (gnus-narrow-to-page))
-    ))
+  (gnus-eval-in-buffer-window 
+   gnus-article-buffer
+   (widen)
+   (goto-char (point-max))
+   (and gnus-break-pages (gnus-narrow-to-page))))
 
 (defun gnus-summary-show-article ()
   "Force re-fetching of the current article."
@@ -6736,7 +6860,8 @@ If ARG is a negative number, hide the unwanted header lines."
            (if (< arg 0) (run-hooks 'gnus-article-display-hook)))
        (if (text-property-any 1 (point-max) 'invisible t)
            (remove-text-properties 1 (point-max) '(invisible t))
-         (run-hooks 'gnus-article-display-hook))))))
+         (let ((gnus-have-all-headers nil))
+           (run-hooks 'gnus-article-display-hook)))))))
 
 (defun gnus-summary-show-all-headers ()
   "Make all header lines visible."
@@ -6805,7 +6930,8 @@ and `request-accept' functions. (Ie. mail newsgroups at present.)"
                       (if (> (length articles) 1)
                           (format "these %d articles" (length articles))
                         "this article"))
-              gnus-active-hashtb nil t)))
+              gnus-active-hashtb nil t 
+              (gnus-group-real-prefix gnus-newsgroup-name))))
     (or (gnus-check-backend-function 'request-accept-article 
                                     (or select-method to-newsgroup))
        (error "%s does not support article moving" to-newsgroup))
@@ -6813,13 +6939,16 @@ and `request-accept' functions. (Ie. mail newsgroups at present.)"
     (while articles
       (if (setq art-group
                (gnus-request-move-article 
-                (car articles)
-                gnus-newsgroup-name 
-                (nth 1 (gnus-find-method-for-group gnus-newsgroup-name))
+                (car articles)                   ; Article to move
+                gnus-newsgroup-name              ; From newsgrouo
+                (nth 1 (gnus-find-method-for-group 
+                        gnus-newsgroup-name))    ; Server
                 (list 'gnus-request-accept-article 
                       (if select-method
                           (quote select-method)
-                        to-newsgroup))))
+                        to-newsgroup)
+                      (not (cdr articles)))     ; Accept form
+                (not (cdr articles))))          ; Only save nov last time
          (let* ((buffer-read-only nil)
                 (entry 
                  (or
@@ -6868,6 +6997,72 @@ and `request-accept' functions. (Ie. mail newsgroups at present.)"
             (gnus-methods-using 'respool) nil t)))
   (gnus-summary-move-article n nil (intern respool-method)))
 
+;; Suggested by gregj@unidata.com (Gregory J. Grubbs).
+(defun gnus-summary-copy-article (n &optional to-newsgroup select-method)
+  "Move the current article to a different newsgroup.
+If N is a positive number, move the N next articles.
+If N is a negative number, move the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+move those articles instead.
+If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to. 
+If SELECT-METHOD is symbol, do not move to a specific newsgroup, but
+re-spool using this method.
+For this function to work, the newsgroup that you want to move to have
+to support the `request-move' and `request-accept'
+functions. (Ie. mail newsgroups at present.)"
+  (interactive "P")
+  (gnus-set-global-variables)
+  (let ((articles (gnus-summary-work-articles n))
+       (copy-buf (get-buffer-create "*copy work*"))
+       art-group)
+    (buffer-disable-undo copy-buf)
+    (if (and (not to-newsgroup) (not select-method))
+       (setq to-newsgroup
+             (completing-read 
+              (format "Where do you want to copy %s? "
+                      (if (> (length articles) 1)
+                          (format "these %d articles" (length articles))
+                        "this article"))
+              gnus-active-hashtb nil t 
+              (gnus-group-real-prefix gnus-newsgroup-name))))
+    (or (gnus-check-backend-function 'request-accept-article 
+                                    (or select-method to-newsgroup))
+       (error "%s does not support article copying" to-newsgroup))
+    (message "Moving to %s: %s..." (or select-method to-newsgroup) articles)
+    (while articles
+      (if (setq art-group
+               (save-excursion
+                 (set-buffer copy-buf)
+                 (gnus-request-article-this-buffer
+                  (car articles) gnus-newsgroup-name)
+                 (gnus-request-accept-article
+                  (if select-method (quote select-method) to-newsgroup)
+                  (not (cdr articles)))))
+         (let* ((entry 
+                 (or
+                  (gnus-gethash (car art-group) gnus-newsrc-hashtb)
+                  (gnus-gethash 
+                   (gnus-group-prefixed-name 
+                    (car art-group) 
+                    (if select-method (list select-method "")
+                      (gnus-find-method-for-group to-newsgroup)))
+                   gnus-newsrc-hashtb)))
+                (info (nth 2 entry))
+                (article (car articles))
+                (marked (nth 3 info)))
+           (if (not (memq article gnus-newsgroup-unreads))
+               (setcar (cdr (cdr info))
+                       (gnus-add-to-range (nth 2 info) 
+                                          (list (cdr art-group)))))
+           ;; !!! Here one should copy all the marks over to the new
+           ;; newsgroup, but I couldn't be bothered. nth on that!
+           )
+       (message "Couldn't copy article %s" (car articles)))
+      (gnus-summary-remove-process-mark (car articles))
+      (setq articles (cdr articles)))
+    (kill-buffer copy-buf)))
+      
+
 ;; Summary score commands.
 
 ;; Suggested by boubaker@cenatls.cena.dgac.fr.
@@ -6891,8 +7086,8 @@ and `request-accept' functions. (Ie. mail newsgroups at present.)"
     (let ((buffer-read-only nil))
       ;; Set score.
       (gnus-summary-update-mark
-       (if (= n gnus-summary-default-score) ? 
-        (if (< n gnus-summary-default-score
+       (if (= n (or gnus-summary-default-score 0)) ? 
+        (if (< n (or gnus-summary-default-score 0)
             gnus-score-below-mark gnus-score-over-mark)) 'score))
     (let* ((article (gnus-summary-article-number))
           (score (assq article gnus-newsgroup-scored)))
@@ -6975,8 +7170,7 @@ If UNMARK is negative, tick articles."
     (gnus-summary-next-article t (and gnus-auto-select-same
                                      (gnus-summary-subject-string)))
     (message "%d articles are marked as %s"
-            count (if unmark "unread" "read"))
-    ))
+            count (if unmark "unread" "read"))))
 
 (defun gnus-summary-kill-same-subject (unmark)
   "Mark articles which has the same subject as read. 
@@ -6993,8 +7187,7 @@ If UNMARK is negative, tick articles."
        ;; Go to next unread subject.
        (gnus-summary-next-subject 1 t))
     (message "%d articles are marked as %s"
-            count (if unmark "unread" "read"))
-    ))
+            count (if unmark "unread" "read"))))
 
 (defun gnus-summary-mark-same-subject (subject &optional unmark)
   "Mark articles with same SUBJECT as read, and return marked number.
@@ -7016,15 +7209,13 @@ If optional argument UNMARK is negative, mark articles as unread instead."
               (gnus-summary-tick-article nil t))
              (t
               (gnus-summary-tick-article)))
-       (setq count (1+ count))
-       ))
+       (setq count (1+ count))))
     ;; Hide killed thread subtrees.  Does not work properly always.
     ;;(and (null unmark)
     ;;     gnus-thread-hide-killed
     ;;    (gnus-summary-hide-thread))
     ;; Return number of articles marked as read.
-    count
-    ))
+    count))
 
 (defun gnus-summary-mark-as-processable (n &optional unmark)
   "Set the process mark on the next N articles.
@@ -7249,7 +7440,8 @@ returned."
        (mark (or mark gnus-dread-mark)))
   (while (and (> n 0)
              (gnus-summary-mark-article nil mark)
-             (zerop (gnus-summary-next-subject (if backward -1 1))))
+             (zerop (gnus-summary-next-subject 
+                     (if backward -1 1) gnus-summary-goto-unread)))
     (setq n (1- n)))
   (if (/= 0 n) (message "No more %sarticles" (if mark "" "unread ")))
   (gnus-set-mode-line 'summary)
@@ -7266,8 +7458,12 @@ marked."
   ;; If no mark is given, then we check auto-expiring.
   (and (or (not mark)
           (and (numberp mark) (or (= mark gnus-killed-mark)
+                                  (= mark gnus-dread-mark)
+                                  (= mark gnus-catchup-mark)
+                                  (= mark gnus-low-score-mark)
                                   (= mark gnus-read-mark))))
-       (and gnus-newsgroup-auto-expire (setq mark gnus-expirable-mark)))
+       gnus-newsgroup-auto-expire 
+       (setq mark gnus-expirable-mark))
   (let* ((buffer-read-only nil)
         (mark (or (and (stringp mark) (aref mark 0)) mark gnus-dread-mark))
         (article (or article (gnus-summary-article-number))))
@@ -7296,7 +7492,8 @@ marked."
       (delete-char 1)
       (and (memq 'gnus-mark plist) (setcar (cdr (memq 'gnus-mark plist)) mark))
       (insert mark)
-      (and plist (add-text-properties (1- (point)) (point) plist)))))
+      (and plist (add-text-properties (1- (point)) (point) plist))
+      (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."
@@ -7338,7 +7535,7 @@ marked."
 (defalias 'gnus-summary-mark-as-unread-forward 
   'gnus-summary-tick-article-forward)
 (make-obsolete 'gnus-summary-mark-as-unread-forward 
-              'gnus-summary-tick-article--forward)
+              'gnus-summary-tick-article-forward)
 (defun gnus-summary-tick-article-forward (n)
   "Tick N articles forwards.
 If N is negative, tick backwards instead.
@@ -7346,8 +7543,10 @@ The difference between N and the number of articles ticked is returned."
   (interactive "p")
   (gnus-summary-mark-forward n gnus-ticked-mark))
 
-(defalias 'gnus-summary-mark-as-unread-backward 'gnus-summary-tick-article-backward)
-(make-obsolete 'gnus-summary-mark-as-unread-backward 'gnus-summary-tick-article-backward)
+(defalias 'gnus-summary-mark-as-unread-backward 
+  'gnus-summary-tick-article-backward)
+(make-obsolete 'gnus-summary-mark-as-unread-backward 
+              'gnus-summary-tick-article-backward)
 (defun gnus-summary-tick-article-backward (n)
   "Tick N articles backwards.
 The difference between N and the number of articles ticked is returned."
@@ -7398,6 +7597,13 @@ The difference between N and the number of marks cleared is returned."
   (interactive "p")
   (gnus-summary-mark-forward (- n) gnus-unread-mark))
 
+(defun gnus-summary-mark-unread-as-read ()
+  "Intended to be used by `gnus-summary-mark-article-hook'."
+  (or (memq gnus-current-article gnus-newsgroup-marked)
+      (memq gnus-current-article gnus-newsgroup-dormant)
+      (memq gnus-current-article gnus-newsgroup-expirable)
+      (gnus-summary-mark-as-read gnus-current-article gnus-read-mark)))
+
 ;; Fix by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defalias 'gnus-summary-delete-marked-as-read 
   'gnus-summary-remove-lines-marked-as-read)
@@ -7426,17 +7632,11 @@ The difference between N and the number of marks cleared is returned."
   (save-excursion
     (set-buffer gnus-summary-buffer)
     (let ((buffer-read-only nil)
-          (marks (concat "^[" marks "]"))
-          beg)
+          (marks (concat "^[" marks "]")))
       (goto-char (point-min))
       (while (search-forward-regexp marks (point-max) t)
-       (progn
-         (move-to-column 0)
-         (setq beg (point))
-         (forward-line 1)
-         ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>
-         (append-to-buffer gnus-newsgroup-expunged-buffer beg (point))
-         (delete-region beg (point)))))
+       (delete-region (progn (beginning-of-line) (point))
+                      (progn (forward-line 1) (point)))))
     (or (zerop (buffer-size))
        (if (eobp)
            (gnus-summary-prev-subject 1)
@@ -7447,7 +7647,7 @@ The difference between N and the number of marks cleared is returned."
   (interactive "P")
   (setq score (if score
                  (prefix-numeric-value score)
-               gnus-summary-default-score))
+               (or gnus-summary-default-score 0)))
   (save-excursion
     (set-buffer gnus-summary-buffer)
     (goto-char (point-min))
@@ -7458,7 +7658,6 @@ The difference between N and the number of marks cleared is returned."
            (progn
              (setq beg (point))
              (forward-line 1)
-             (append-to-buffer gnus-newsgroup-expunged-buffer beg (point))
              (delete-region beg (point)))
          (forward-line 1)))
       ;; Adjust point.
@@ -7467,31 +7666,19 @@ The difference between N and the number of marks cleared is returned."
              (gnus-summary-prev-subject 1)
            (gnus-summary-position-cursor))))))
 
-(defun gnus-summary-mark-below (score mark)
-  "Mark articles with score less than SCORE with MARK."
-  (interactive "P\ncMark: ")
-  (setq score (if score
-                 (prefix-numeric-value score)
-               gnus-summary-default-score))
-  (save-excursion
-    (set-buffer gnus-summary-buffer)
-    (goto-char (point-min))
-    (while (not (eobp))
-      (if (< (gnus-summary-article-score) score)
-         (progn
-           (gnus-summary-mark-article nil (char-to-string mark))
-           (forward-line 1))
-       (forward-line 1)))))
-
-;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-summary-set-mark-below (score)
-  "Automatically mark articles with score below SCORE as read."
-  (interactive "P")
+(defun gnus-summary-mark-below (score mark)
+  "Mark articles with score less than SCORE with MARK."
+  (interactive "P\ncMark: ")
   (setq score (if score
                  (prefix-numeric-value score)
-               gnus-summary-default-score))
-  (setq gnus-summary-mark-below score)
-  (gnus-summary-update-lines))
+               (or gnus-summary-default-score 0)))
+  (save-excursion
+    (set-buffer gnus-summary-buffer)
+    (goto-char (point-min))
+    (while (not (eobp))
+      (and (< (gnus-summary-article-score) score)
+          (gnus-summary-mark-article nil mark))
+      (forward-line 1))))
 
 (defun gnus-summary-kill-below (score)
   "Mark articles with score below SCORE as read."
@@ -7509,11 +7696,11 @@ The difference between N and the number of marks cleared is returned."
   (gnus-summary-mark-above score gnus-ticked-mark))
 
 (defun gnus-summary-mark-above (score mark)
-  "Mark articles with score less than SCORE with MARK."
+  "Mark articles with score over SCORE with MARK."
   (interactive "P\ncMark: ")
   (setq score (if score
                  (prefix-numeric-value score)
-               gnus-summary-default-score))
+               (or gnus-summary-default-score 0)))
   (save-excursion
     (set-buffer gnus-summary-buffer)
     (goto-char (point-min))
@@ -7526,33 +7713,46 @@ The difference between N and the number of marks cleared is returned."
 
 ;; Suggested by Daniel Quinlan <quinlan@best.com>.  
 (defun gnus-summary-show-all-expunged ()
-  "Show all previously expunge articles."
+  "Display all the hidden articles that were expunged for low scores."
   (interactive)
   (let ((buffer-read-only nil))
-    (save-excursion
-      (if (and gnus-newsgroup-expunged-buffer
-              (progn
-                (set-buffer gnus-newsgroup-expunged-buffer)
-                (not (zerop (buffer-size)))))
-         (progn
-           (append-to-buffer gnus-summary-buffer (point-min) (point-max))
-           (erase-buffer))
-       (error "No lines expunged")))))
+    (let ((scored gnus-newsgroup-scored)
+         headers h)
+      (while scored
+       (or (gnus-summary-goto-subject (car (car scored)))
+           (and (setq h (gnus-get-header-by-number (car (car scored))))
+                (< (cdr (car scored)) gnus-summary-expunge-below)
+                (setq headers (cons h headers))))
+       (setq scored (cdr scored)))
+      (or headers (error "No expunged articles hidden."))
+      (goto-char (point-min))
+      (save-excursion 
+       (gnus-summary-prepare-threads (nreverse headers) 0)))
+    (goto-char (point-min))
+    (gnus-summary-position-cursor)))
 
 (defun gnus-summary-show-all-dormant ()
   "Display all the hidden articles that are marked as dormant."
   (interactive)
-  (let ((int gnus-newsgroup-dormant-subjects)
-       (buffer-read-only nil))
-    (if (not int)
-       (error "No dormant articles hidden."))
+  (let ((buffer-read-only nil))
     (goto-char (point-min))
-    (save-excursion
-      (while int
-       (insert (cdr (car int)))
-       (setq int (cdr int))))
-    (gnus-summary-position-cursor)
-    (setq gnus-newsgroup-dormant-subjects nil)))
+    (let ((dormant gnus-newsgroup-dormant)
+         headers h)
+      (while dormant
+       (or (gnus-summary-goto-subject (car dormant))
+           (and (setq h (gnus-get-header-by-number (car dormant)))
+                (setq headers (cons h headers))))
+       (setq dormant (cdr dormant)))
+      (or headers (error "No dormant articles hidden."))
+      (save-excursion (gnus-summary-prepare-threads (nreverse headers) 0)))
+    (goto-char (point-min))
+    (gnus-summary-position-cursor)))
+
+(defun gnus-summary-hide-all-dormant ()
+  "Hide all dormant articles."
+  (interactive)
+  (gnus-summary-remove-lines-marked-with (char-to-string gnus-dormant-mark))
+  (gnus-summary-position-cursor))
 
 (defun gnus-summary-catchup (all &optional quietly to-here)
   "Mark all articles not marked as unread in this newsgroup as read.
@@ -7562,27 +7762,29 @@ If TO-HERE is non-nil, it should be a point in the buffer. All
 articles before this point will be marked as read.
 The number of articles marked as read is returned."
   (interactive "P")
-  (if (or quietly
-         (not gnus-interactive-catchup) ;Without confirmation?
-         gnus-expert-user
-         (gnus-y-or-n-p
-          (if all
-              "Mark absolutely all articles as read? "
-            "Mark all unread articles as read? ")))
-      (let ((unreads (length gnus-newsgroup-unreads)))
-       (if (gnus-summary-first-subject (not all))
-           (while (and (gnus-summary-mark-as-read nil gnus-catchup-mark)
-                       (if to-here (< (point) to-here) t)
-                       (gnus-summary-search-subject nil (not all)))))
-       (- unreads (length gnus-newsgroup-unreads))))
-  (gnus-summary-position-cursor))
+  (prog1
+      (if (or quietly
+             (not gnus-interactive-catchup) ;Without confirmation?
+             gnus-expert-user
+             (gnus-y-or-n-p
+              (if all
+                  "Mark absolutely all articles as read? "
+                "Mark all unread articles as read? ")))
+         (let ((unreads (length gnus-newsgroup-unreads)))
+           (if (gnus-summary-first-subject (not all))
+               (while (and (gnus-summary-mark-as-read nil gnus-catchup-mark)
+                           (if to-here (< (point) to-here) t)
+                           (gnus-summary-search-subject nil (not all)))))
+           (- unreads (length gnus-newsgroup-unreads))))
+    (setq gnus-newsgroup-unreads gnus-newsgroup-marked)
+    (gnus-summary-position-cursor)))
 
 (defun gnus-summary-catchup-to-here (&optional all)
   "Mark all unticked articles before the current one as read.
 If ALL is non-nil, also mark ticked and dormant articles as read."
   (interactive)
   (beginning-of-line)
-  (gnus-summary-catchup all nil (point))
+  (gnus-summary-catchup all t (point))
   (gnus-summary-position-cursor))
 
 (defun gnus-summary-catchup-all (&optional quietly)
@@ -7611,12 +7813,13 @@ If prefix argument ALL is non-nil, all articles are marked as read."
   "Toggle showing conversation threads.
 If ARG is positive number, turn showing conversation threads on."
   (interactive "P")
-  (let ((current (gnus-summary-article-number)))
+  (let ((current (or (gnus-summary-article-number) gnus-newsgroup-end)))
     (setq gnus-show-threads
          (if (null arg) (not gnus-show-threads)
            (> (prefix-numeric-value arg) 0)))
     (gnus-summary-prepare)
-    (gnus-summary-goto-subject current)))
+    (gnus-summary-goto-subject current)
+    (gnus-summary-position-cursor)))
 
 (defun gnus-summary-show-all-threads ()
   "Show all threads."
@@ -7648,8 +7851,7 @@ Returns nil if no thread was there to be shown."
     (goto-char (point-min))
     (gnus-summary-hide-thread)
     (while (and (not (eobp)) (zerop (forward-line 1)))
-      (gnus-summary-hide-thread))
-    )
+      (gnus-summary-hide-thread)))
   (gnus-summary-position-cursor))
 
 (defun gnus-summary-hide-thread ()
@@ -7700,7 +7902,7 @@ done."
              (gnus-summary-go-to-next-thread backward))
     (setq n (1- n)))
   (gnus-summary-position-cursor)
-  (if (/= 0 n) (message "No more threads" ))
+  (if (/= 0 n) (message "No more threads"))
   n))
 
 (defun gnus-summary-prev-thread (n)
@@ -7746,7 +7948,7 @@ taken."
                (gnus-summary-go-down-thread)))
     (setq n (1- n)))
   (gnus-summary-position-cursor)
-  (if (/= 0 n) (message "Can't go further" ))
+  (if (/= 0 n) (message "Can't go further"))
   n))
 
 (defun gnus-summary-up-thread (n)
@@ -7802,7 +8004,8 @@ Argument REVERSE means reverse order."
   (interactive "P")
   (gnus-summary-sort
    (lambda ()
-     (let ((extract (gnus-extract-address-components
+     (let ((extract (funcall
+                    gnus-extract-address-components
                     (header-from (gnus-get-header-by-number
                                   (gnus-summary-article-number))))))
        (or (car extract) (cdr extract))))
@@ -7847,10 +8050,10 @@ Timezone package is used."
         (year   (aref date 0))
         (month  (aref date 1))
         (day    (aref date 2)))
-    (timezone-make-sortable-date year month day 
-                                (timezone-make-time-string
-                                 (aref date 3) (aref date 4) (aref date 5)))
-    ))
+    (timezone-make-sortable-date 
+     year month day 
+     (timezone-make-time-string
+      (aref date 3) (aref date 4) (aref date 5)))))
 
 
 ;; Summary saving commands.
@@ -8029,10 +8232,11 @@ is initialized from the SAVEDIR environment variable."
     (or (gnus-summary-goto-subject article)
        (error (format "No such article: %d" article)))
     (gnus-summary-position-cursor)
-    (if (eq gnus-view-pseudos 'automatic)
+    (if gnus-view-pseudos
        (while pslist
          (and (assq 'execute (car pslist))
-              (gnus-execute-command (cdr (assq 'execute (car pslist)))))
+              (gnus-execute-command (cdr (assq 'execute (car pslist)))
+                                    (eq gnus-view-pseudos 'not-confirm)))
          (setq pslist (cdr pslist)))
       (save-excursion
        (while pslist
@@ -8056,10 +8260,7 @@ is initialized from the SAVEDIR environment variable."
 
 (defun gnus-request-pseudo-article (props)
   (cond ((assq 'execute props)
-        (gnus-execute-command (cdr (assq 'execute props))))
-       ((assq 'digest props)
-        )
-       )
+        (gnus-execute-command (cdr (assq 'execute props)))))
   (let ((gnus-current-article (gnus-summary-article-number)))
     (run-hooks 'gnus-mark-article-hook)))
 
@@ -8106,25 +8307,35 @@ MATCH is the string we are looking for.
 TYPE is a flag indicating if it is a regexp or substring.
 SCORE is the score to add.
 DATE is the expire date."
-  (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 "Expire kill? ")
-                        (current-time-string)
-                      nil)))
+  (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 "Expire kill? ")
+            (current-time-string)
+          nil)))
   (and prompt (setq match (read-string "Match: " match)))
   (let ((score (gnus-score-default score)))
     (gnus-summary-score-effect header match type score)
-  
-    (gnus-summary-score-effect header match type score)
-    (gnus-score-set header
-                   (cons (list match type score date) 
-                         (gnus-score-get header) ))
-    (gnus-score-set 'touched t)))
+    (and (= score gnus-score-interactive-default-score)
+        (setq score nil))
+    (let ((new (cond (type
+                 (list match score (and date (gnus-day-number date)) type))
+                (date
+                 (list match score (gnus-day-number date)))
+                (score
+                 (list match score))
+                (t
+                 (list match))))
+         (old (gnus-score-get header)))
+      (gnus-score-set
+       header
+       (if old (cons new old) (list new))))
+    (gnus-score-set 'touched '(t))))
 
 (defun gnus-summary-score-effect (header match type score)
   "Simulate the effect of a score file entry.
@@ -8173,33 +8384,43 @@ SCORE is the score to add."
 
 (defun gnus-summary-temporarily-lower-by-subject (level)
   "Temporarily lower score by LEVEL for current subject.
-See `gnus-kill-expiry-days'."
+See `gnus-score-expiry-days'."
   (interactive "P")
   (gnus-summary-score-entry
    "subject" (gnus-simplify-subject-re (gnus-summary-header "subject"))
-   nil (- (gnus-score-default level) )
+   nil (- (gnus-score-default level))
    (current-time-string) t))
 
 (defun gnus-summary-temporarily-lower-by-author (level)
   "Temporarily lower score by LEVEL for current author.
-See `gnus-kill-expiry-days'."
+See `gnus-score-expiry-days'."
   (interactive "P")
   (gnus-summary-score-entry
    "from" (gnus-summary-header "from") nil (- (gnus-score-default level)) 
    (current-time-string) t))
 
+(defun gnus-summary-temporarily-lower-by-id (level)
+  "Temporarily lower score by LEVEL for current message-id.
+See `gnus-score-expiry-days'."
+  (interactive "P")
+  (gnus-summary-score-entry
+   "message-id" (gnus-summary-header "message-id") 
+   nil (- (gnus-score-default level)) 
+   (current-time-string)))
+
 (defun gnus-summary-temporarily-lower-by-xref (level)
   "Temporarily lower score by LEVEL for current xref.
-See `gnus-kill-expiry-days'."
+See `gnus-score-expiry-days'."
   (interactive "P")
-  (gnus-summary-score-crossposting (- (gnus-score-default level)) (current-time-string)))
+  (gnus-summary-score-crossposting 
+   (- (gnus-score-default level)) (current-time-string)))
 
 (defun gnus-summary-temporarily-lower-by-thread (level)
   "Temporarily lower score by LEVEL for current thread.
-See `gnus-kill-expiry-days'."
+See `gnus-score-expiry-days'."
   (interactive "P")
   (gnus-summary-score-entry
-   "references" (gnus-summary-header "id")
+   "references" (gnus-summary-header "message-id")
    nil (- (gnus-score-default level)) (current-time-string)))
 
 (defun gnus-summary-lower-by-subject (level)
@@ -8214,7 +8435,15 @@ See `gnus-kill-expiry-days'."
   "Lower score by LEVEL for current author."
   (interactive "P")
   (gnus-summary-score-entry
-   "from" (gnus-summary-header "from") nil (- (gnus-score-default level)) nil t))
+   "from" (gnus-summary-header "from") nil 
+   (- (gnus-score-default level)) nil t))
+
+(defun gnus-summary-lower-by-id (level)
+  "Lower score by LEVEL for current message-id."
+  (interactive "P")
+  (gnus-summary-score-entry
+   "message-id" (gnus-summary-header "message-id") nil 
+   (- (gnus-score-default level)) nil))
 
 (defun gnus-summary-lower-by-xref (level)
   "Lower score by LEVEL for current xref."
@@ -8224,15 +8453,12 @@ See `gnus-kill-expiry-days'."
 (defun gnus-summary-lower-followups-to-author (level)
   "Lower score by LEVEL for all followups to the current author."
   (interactive "P")
-  (gnus-kill-file-lower-followups-to-author
-   (gnus-score-default level)
-   (let ((article (gnus-summary-article-number)))
-     (if article (gnus-get-header-by-number article)
-       (error "No article on current line")))))
+  (gnus-summary-raise-followups-to-author
+   (- (gnus-score-default level))))
 
 (defun gnus-summary-temporarily-raise-by-subject (level)
   "Temporarily raise score by LEVEL for current subject.
-See `gnus-kill-expiry-days'."
+See `gnus-score-expiry-days'."
   (interactive "P")
   (gnus-summary-score-entry
    "subject" (gnus-simplify-subject-re (gnus-summary-header "subject"))
@@ -8240,23 +8466,31 @@ See `gnus-kill-expiry-days'."
 
 (defun gnus-summary-temporarily-raise-by-author (level)
   "Temporarily raise score by LEVEL for current author.
-See `gnus-kill-expiry-days'."
+See `gnus-score-expiry-days'."
   (interactive "P")
   (gnus-summary-score-entry
    "from" (gnus-summary-header "from") nil level (current-time-string) t))
 
+(defun gnus-summary-temporarily-raise-by-id (level)
+  "Temporarily raise score by LEVEL for current message-id.
+See `gnus-score-expiry-days'."
+  (interactive "P")
+  (gnus-summary-score-entry
+   "message-id" (gnus-summary-header "message-id") 
+   nil level (current-time-string)))
+
 (defun gnus-summary-temporarily-raise-by-xref (level)
   "Temporarily raise score by LEVEL for current xref.
-See `gnus-kill-expiry-days'."
+See `gnus-score-expiry-days'."
   (interactive "P")
   (gnus-summary-score-crossposting level (current-time-string)))
 
 (defun gnus-summary-temporarily-raise-by-thread (level)
   "Temporarily raise score by LEVEL for current thread.
-See `gnus-kill-expiry-days'."
+See `gnus-score-expiry-days'."
   (interactive "P")
   (gnus-summary-score-entry
-   "references" (gnus-summary-header "id")
+   "references" (gnus-summary-header "message-id")
    nil level (current-time-string)))
 
 (defun gnus-summary-raise-by-subject (level)
@@ -8272,38 +8506,43 @@ See `gnus-kill-expiry-days'."
   (gnus-summary-score-entry
    "from" (gnus-summary-header "from") nil level nil t))
 
+(defun gnus-summary-raise-by-id (level)
+  "Raise score by LEVEL for current message-id."
+  (interactive "P")
+  (gnus-summary-score-entry
+   "message-id" (gnus-summary-header "message-id") nil level nil))
+
 (defun gnus-summary-raise-by-xref (level)
   "Raise score by LEVEL for current xref."
   (interactive "P")
   (gnus-summary-score-crossposting level nil))
 
-(defun gnus-summary-edit-global-kill ()
-  "Edit a global score file."
-  (interactive)
-  (setq gnus-current-kill-article (gnus-summary-article-number))
-  (gnus-kill-file-edit-file nil)       ;Nil stands for global score file.
-  (message
-   (substitute-command-keys
-    "Editing a global score file (Type \\[gnus-kill-file-exit] to exit)")))
-
 (defun gnus-summary-raise-followups-to-author (level)
   "Raise score by LEVEL for all followups to the current author."
   (interactive "P")
+  (let ((article (gnus-summary-article-number)))
+    (if article (setq gnus-current-headers (gnus-get-header-by-number article))
+      (error "No article on current line")))
   (gnus-kill-file-raise-followups-to-author
-   (gnus-score-default level)
-   (let ((article (gnus-summary-article-number)))
-     (if article (gnus-get-header-by-number article)
-       (error "No article on current line")))))
+   (gnus-score-default level)))
+
+;; Summary kill commands.
+
+(defun gnus-summary-edit-global-kill (article)
+  "Edit the global score file."
+  (interactive (list (gnus-summary-article-number)))
+  (gnus-group-edit-global-kill article))
 
 (defun gnus-summary-edit-local-kill ()
   "Edit a local score file applied to the current newsgroup."
   (interactive)
-  (setq gnus-current-kill-article (gnus-summary-article-number))
-  (gnus-kill-file-edit-file gnus-newsgroup-name)
-  (message
-   (substitute-command-keys
-    "Editing a local score file (Type \\[gnus-kill-file-exit] to exit)")))
-
+  (setq gnus-current-headers 
+       (gnus-gethash 
+        (int-to-string (gnus-summary-article-number))
+        gnus-newsgroup-headers-hashtb-by-number))
+  (gnus-set-global-variables)
+  (gnus-group-edit-local-kill 
+   (gnus-summary-article-number) gnus-newsgroup-name))
 
 \f
 ;;;
@@ -8316,11 +8555,11 @@ See `gnus-kill-expiry-days'."
   (suppress-keymap gnus-article-mode-map)
   (define-key gnus-article-mode-map " " 'gnus-article-next-page)
   (define-key gnus-article-mode-map "\177" 'gnus-article-prev-page)
-  (define-key gnus-article-mode-map "\C-x^" 'gnus-article-refer-article)
+  (define-key gnus-article-mode-map "\C-c^" 'gnus-article-refer-article)
   (define-key gnus-article-mode-map "h" 'gnus-article-show-summary)
   (define-key gnus-article-mode-map "s" 'gnus-article-show-summary)
-  (define-key gnus-article-mode-map "\C-xm" 'gnus-article-mail)
-  (define-key gnus-article-mode-map "\C-xM" 'gnus-article-mail-with-original)
+  (define-key gnus-article-mode-map "\C-c\C-m" 'gnus-article-mail)
+  (define-key gnus-article-mode-map "\C-c\C-M" 'gnus-article-mail-with-original)
   (define-key gnus-article-mode-map "?" 'gnus-article-describe-briefly)
   
   ;; Duplicate almost all summary keystrokes in the article mode map.
@@ -8352,9 +8591,7 @@ The following commands are available:
 \\[gnus-article-mail]\t Send a reply to the address near point
 \\[gnus-article-mail-with-original]\t Send a reply to the address near point; include the original article
 \\[gnus-article-describe-briefly]\t Describe the current mode briefly
-\\[gnus-info-find-node]\t Go to the Gnus info node
-
-"
+\\[gnus-info-find-node]\t Go to the Gnus info node"
   (interactive)
   (if gnus-visual (gnus-article-make-menu-bar))
   (kill-all-local-variables)
@@ -8393,7 +8630,9 @@ The following commands are available:
 
   ;; We only request an article by message-id when we do not have the
   ;; headers for it, so we'll have to get those.
-  (and (stringp article) (gnus-read-header article))
+  (and (stringp article) 
+       (let ((gnus-override-method gnus-refer-article-method))
+        (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
@@ -8413,8 +8652,10 @@ The following commands are available:
   (if article
       (progn
        (erase-buffer)
-       (and (gnus-request-article article group (current-buffer))
-           'article))
+       (let ((gnus-override-method 
+             (and (stringp article) gnus-refer-article-method)))
+        (and (gnus-request-article article group (current-buffer))
+             'article)))
     'pseudo))
 
 (defun gnus-read-header (id)
@@ -8476,7 +8717,7 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                  (and (numberp article) 
                       (gnus-summary-mark-as-read article gnus-canceled-mark))
                  (message "No such article (may be canceled)")
-                 (ding) )
+                 (ding))
                (setq gnus-article-current nil)
                nil)
            (if (not (eq result 'article))
@@ -8484,11 +8725,12 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                  (save-excursion
                    (set-buffer summary-buffer)
                    (setq gnus-last-article gnus-current-article
+                         gnus-newsgroup-history (cons gnus-current-article
+                                                      gnus-newsgroup-history)
                          gnus-current-article 0
                          gnus-current-headers nil
                          gnus-article-current nil)
                    (gnus-configure-windows 'article)
-                   (gnus-set-mode-line 'summary)
                    (gnus-set-global-variables))
                  (gnus-set-mode-line 'article))
              ;; The result from the `request' was an actual article -
@@ -8500,14 +8742,16 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                  ;; `gnus-current-article' must be an article number.
                  (save-excursion
                    (set-buffer summary-buffer)
-                   (setq gnus-last-article gnus-current-article)
-                   (setq gnus-current-article article)
-                   (setq gnus-current-headers 
-                         (gnus-get-header-by-number gnus-current-article))
-                   (setq gnus-article-current 
+                   (setq gnus-last-article gnus-current-article
+                         gnus-newsgroup-history (cons gnus-current-article
+                                                      gnus-newsgroup-history)
+                         gnus-current-article article
+                         gnus-current-headers 
+                         (gnus-get-header-by-number gnus-current-article)
+                         gnus-article-current 
                          (cons gnus-newsgroup-name gnus-current-article))
-                   (gnus-set-mode-line 'summary)
                    (run-hooks 'gnus-mark-article-hook)
+                   (gnus-set-mode-line 'summary)
                    (and gnus-visual 
                         (run-hooks 'gnus-visual-mark-article-hook))
                    ;; Set the global newsgroup variables here.
@@ -8704,8 +8948,9 @@ please do mail it to me."
 (defun gnus-article-remove-cr ()
   (interactive)
   (save-excursion
+    (set-buffer gnus-article-buffer)
     (let ((buffer-read-only nil))
-      (set-buffer gnus-article-buffer)
+      (goto-char (point-min))
       (while (search-forward "\r" nil t)
        (replace-match "")))))
 
@@ -8786,10 +9031,8 @@ please do mail it to me."
                  (narrow-to-region (point) (point-max))
                  (goto-char (1+ (point-min)))
                  (rmail-count-new-messages t)
-                 (rmail-show-message msg))))))
-      )
-    (kill-buffer tmpbuf)
-    ))
+                 (rmail-show-message msg)))))))
+    (kill-buffer tmpbuf)))
 
 (defun gnus-output-to-file (file-name)
   "Append the current article to a file named FILE-NAME."
@@ -8806,8 +9049,7 @@ please do mail it to me."
       (goto-char (point-max))
       (insert "\n")
       (append-to-file (point-min) (point-max) file-name))
-    (kill-buffer tmpbuf)
-    ))
+    (kill-buffer tmpbuf)))
 
 (defun gnus-convert-article-to-rmail ()
   "Convert article in current buffer to Rmail message format."
@@ -8853,12 +9095,10 @@ thus showing a page other than the one point was originally in."
                        ;; Otherwise, show text starting with following line.
                        (if (and (eolp) (not (bobp)))
                            (forward-line 1))
-                       (point)))
-    ))
+                       (point)))))
 
 (defun gnus-gmt-to-local ()
-  "Rewrite Date: field described in GMT to local in current buffer.
-The variable gnus-local-timezone is used for local time zone.
+  "Rewrite Date header described in GMT to local in current buffer.
 Intended to be used with gnus-article-prepare-hook."
   (save-excursion
     (save-restriction
@@ -8872,9 +9112,8 @@ Intended to be used with gnus-article-prepare-hook."
                (date (buffer-substring (match-beginning 1) (match-end 1))))
            (delete-region (match-beginning 1) (match-end 1))
            (insert
-            (timezone-make-date-arpa-standard date nil gnus-local-timezone))
-           ))
-      )))
+            (timezone-make-date-arpa-standard 
+             date nil (current-time-zone))))))))
 
 
 ;; Article mode commands
@@ -8897,16 +9136,14 @@ Argument LINES specifies lines to be scrolled up."
                  (widen) (forward-line 1) (eobp)))) ;Real end-of-buffer?
          t                             ;Nothing more.
        (gnus-narrow-to-page 1)         ;Go to next page.
-       nil
-       )
+       nil)
     ;; More in this page.
     (condition-case ()
        (scroll-up lines)
       (end-of-buffer
        ;; Long lines may cause an end-of-buffer error.
        (goto-char (point-max))))
-    nil
-    ))
+    nil))
 
 (defun gnus-article-prev-page (lines)
   "Show previous page of current article.
@@ -9032,108 +9269,69 @@ ROT47 will be performed for Japanese text in any case."
 
 \f
 ;;;
-;;; Gnus Score File Mode
+;;; Gnus Kill File Mode
 ;;;
 
+(defvar gnus-kill-file-mode-map nil)
+
 (if gnus-kill-file-mode-map
     nil
   (setq gnus-kill-file-mode-map (copy-keymap emacs-lisp-mode-map))
-  (define-key gnus-kill-file-mode-map "\C-c\C-x"
-    'gnus-kill-file-set-expunge-below)
-  (define-key gnus-kill-file-mode-map "\C-c@"
-    'gnus-kill-file-set-mark-below)
-  (define-key gnus-kill-file-mode-map "\C-c\C-k\C-s"
-    'gnus-kill-file-temporarily-lower-by-subject)
-  (define-key gnus-kill-file-mode-map "\C-c\C-k\C-a"
-    'gnus-kill-file-temporarily-lower-by-author)
-  (define-key gnus-kill-file-mode-map "\C-c\C-k\C-x"
-    'gnus-kill-file-temporarily-lower-by-xref)
-  (define-key gnus-kill-file-mode-map "\C-c\C-ks"
-    'gnus-kill-file-lower-by-subject)
-  (define-key gnus-kill-file-mode-map "\C-c\C-ka"
-    'gnus-kill-file-lower-by-author)
-  (define-key gnus-kill-file-mode-map "\C-c\C-kt"
-    'gnus-kill-file-lower-by-thread)
-  (define-key gnus-kill-file-mode-map "\C-c\C-kx"
-    'gnus-kill-file-lower-by-xref)
-  (define-key gnus-kill-file-mode-map "\C-c\C-kf"
-    'gnus-kill-file-lower-followups-to-author)
-  (define-key gnus-kill-file-mode-map "\C-c\C-i\C-s"
-    'gnus-kill-file-temporarily-raise-by-subject)
-  (define-key gnus-kill-file-mode-map "\C-c\C-i\C-a"
-    'gnus-kill-file-temporarily-raise-by-author)
-  (define-key gnus-kill-file-mode-map "\C-c\C-i\C-t"
-    'gnus-kill-file-temporarily-raise-by-thread)
-  (define-key gnus-kill-file-mode-map "\C-c\C-i\C-x"
-    'gnus-kill-file-temporarily-raise-by-xref)
-  (define-key gnus-kill-file-mode-map "\C-c\C-is"
-    'gnus-kill-file-raise-by-subject)
-  (define-key gnus-kill-file-mode-map "\C-c\C-ia"
-    'gnus-kill-file-raise-by-author)
-  (define-key gnus-kill-file-mode-map "\C-c\C-ix"
-    'gnus-kill-file-raise-by-xref)
-  (define-key gnus-kill-file-mode-map "\C-c\C-if"
-    'gnus-kill-file-raise-followups-to-author)
-  (define-key gnus-kill-file-mode-map "\C-c\C-a" 'gnus-kill-file-apply-buffer)
-  (define-key gnus-kill-file-mode-map "\C-c\C-e" 'gnus-kill-file-apply-last-sexp)
-  (define-key gnus-kill-file-mode-map "\C-c\C-c" 'gnus-kill-file-exit)
-  (define-key gnus-kill-file-mode-map "\C-c\C-i" 'gnus-info-find-node))
+  (define-key gnus-kill-file-mode-map 
+    "\C-c\C-k\C-s" 'gnus-kill-file-kill-by-subject)
+  (define-key gnus-kill-file-mode-map
+    "\C-c\C-k\C-a" 'gnus-kill-file-kill-by-author)
+  (define-key gnus-kill-file-mode-map
+    "\C-c\C-k\C-a" 'gnus-kill-file-kill-by-thread)
+  (define-key gnus-kill-file-mode-map 
+    "\C-c\C-k\C-a" 'gnus-kill-file-kill-by-xref)
+  (define-key gnus-kill-file-mode-map
+    "\C-c\C-a" 'gnus-kill-file-apply-buffer)
+  (define-key gnus-kill-file-mode-map
+    "\C-c\C-e" 'gnus-kill-file-apply-last-sexp)
+  (define-key gnus-kill-file-mode-map 
+    "\C-c\C-c" 'gnus-kill-file-exit))
 
 (defun gnus-kill-file-mode ()
-  "Major mode for editing score files.
-
-In addition to Emacs-Lisp mode, the following commands are available:
-
-\\[gnus-kill-file-set-expunge-below]   Automatically expunge articles below LEVEL.
-\\[gnus-kill-file-set-mark-below]      Automatically mark articles below LEVEL.
-\\[gnus-kill-file-temporarily-lower-by-author] Insert temporary lower command for current author.
-\\[gnus-kill-file-temporarily-lower-by-thread] Insert temporary lower command for current thread.
-\\[gnus-kill-file-temporarily-lower-by-xref]           Insert temporary lower command for current cross-posting.
-\\[gnus-kill-file-lower-by-subject]    Insert permanent lower command for current subject.
-\\[gnus-kill-file-lower-by-author]     Insert permanent lower command for current author.
-\\[gnus-kill-file-lower-followups-to-author]   Insert permanent lower command for followups to the current author.
-\\[gnus-kill-file-lower-by-xref]               Insert permanent lower command for current cross-posting.
-\\[gnus-kill-file-temporarily-raise-by-subject]        Insert temporary raise command for current subject.
-\\[gnus-kill-file-temporarily-raise-by-author] Insert temporary raise command for current author.
-\\[gnus-kill-file-temporarily-raise-by-thread] Insert temporary raise command for current thread.
-\\[gnus-kill-file-temporarily-raise-by-xref]           Insert temporary raise command for current cross-posting.
-\\[gnus-kill-file-raise-by-subject]    Insert permanent raise command for current subject.
-\\[gnus-kill-file-raise-by-author]     Insert permanent raise command for current author.
-\\[gnus-kill-file-raise-followups-to-author]   Insert permanent raise command for followups to the current author.
-\\[gnus-kill-file-raise-by-xref]               Insert permanent raise command for current cross-posting.
-\\[gnus-kill-file-apply-buffer]        Apply current buffer to selected newsgroup.
-\\[gnus-kill-file-apply-last-sexp]     Apply sexp before point to selected newsgroup.
-\\[gnus-kill-file-exit]        Save file and exit editing score file.
-\\[gnus-info-find-node]        Read Info about score files.
-
-  A score file contains Lisp expressions to be applied to a selected
+  "Major mode for editing kill files.
+
+If you are using this mode - you probably shouldn't.  Kill files
+perform badly and paint with a pretty broad brush.  Score files, on
+the other hand, are vastly faster (40x speedup) and give you more
+control over what to do.
+
+In addition to Emacs-Lisp Mode, the following commands are available:
+
+\\{gnus-kill-file-mode-map}
+
+  A kill file contains Lisp expressions to be applied to a selected
 newsgroup.  The purpose is to mark articles as read on the basis of
-some set of regexps.  A global score file is applied to every
-newsgroup, and a local score file is applied to a specified newsgroup.
-Since a global score file is applied to every newsgroup, for better
-performance use a local one.
+some set of regexps.  A global kill file is applied to every newsgroup,
+and a local kill file is applied to a specified newsgroup.  Since a
+global kill file is applied to every newsgroup, for better performance
+use a local one.
 
-  A score file can contain any kind of Emacs Lisp expressions expected
-to be evaluated in the summary buffer.  Writing Lisp programs for this
+  A kill file can contain any kind of Emacs Lisp expressions expected
+to be evaluated in the Summary buffer.  Writing Lisp programs for this
 purpose is not so easy because the internal working of Gnus must be
 well-known.  For this reason, Gnus provides a general function which
 does this easily for non-Lisp programmers.
 
-  The `gnus-kill' function executes commands available in summary mode
+  The `gnus-kill' function executes commands available in Summary Mode
 by their key sequences. `gnus-kill' should be called with FIELD,
 REGEXP and optional COMMAND and ALL.  FIELD is a string representing
 the header field or an empty string.  If FIELD is an empty string, the
 entire article body is searched for.  REGEXP is a string which is
 compared with FIELD value. COMMAND is a string representing a valid
-key sequence in summary mode or Lisp expression. COMMAND defaults to
+key sequence in Summary mode or Lisp expression. COMMAND defaults to
 '(gnus-summary-mark-as-read nil \"X\").  Make sure that COMMAND is
-executed in the summary buffer.  If the second optional argument ALL
+executed in the Summary buffer.  If the second optional argument ALL
 is non-nil, the COMMAND is applied to articles which are already
 marked as read or unread.  Articles which are marked are skipped over
 by default.
 
   For example, if you want to mark articles of which subjects contain
-the string `AI' as read, a possible score file may look like:
+the string `AI' as read, a possible kill file may look like:
 
        (gnus-kill \"Subject\" \"AI\")
 
@@ -9143,16 +9341,16 @@ the following expression:
        (gnus-kill \"Subject\" \"AI\" \"d\")
 
 In this example it is assumed that the command
-`gnus-summary-mark-as-read-forward' is assigned to `d' in summary mode.
+`gnus-summary-mark-as-read-forward' is assigned to `d' in Summary Mode.
 
-  It is possible to remove unnecessary headers which are marked with
-`X' in a score file as follows:
+  It is possible to delete unnecessary headers which are marked with
+`X' in a kill file as follows:
 
        (gnus-expunge \"X\")
 
-  If the summary buffer is empty after applying score files, Gnus will
+  If the Summary buffer is empty after applying kill files, Gnus will
 exit the selected newsgroup normally.  If headers which are marked
-with `D' are deleted in a score file, it is impossible to read articles
+with `D' are deleted in a kill file, it is impossible to read articles
 which are marked as read in the previous Gnus sessions.  Marks other
 than `D' should be used for articles which should really be deleted.
 
@@ -9163,13 +9361,13 @@ gnus-kill-file-mode-hook with no arguments, if that value is non-nil."
   (use-local-map gnus-kill-file-mode-map)
   (set-syntax-table emacs-lisp-mode-syntax-table)
   (setq major-mode 'gnus-kill-file-mode)
-  (setq mode-name "score-file")
+  (setq mode-name "Kill")
   (lisp-mode-variables nil)
   (run-hooks 'emacs-lisp-mode-hook 'gnus-kill-file-mode-hook))
 
 (defun gnus-kill-file-edit-file (newsgroup)
-  "Begin editing a score file for NEWSGROUP.
-If NEWSGROUP is nil, the global score file is selected."
+  "Begin editing a kill file for NEWSGROUP.
+If NEWSGROUP is nil, the global kill file is selected."
   (interactive "sNewsgroup: ")
   (let ((file (gnus-newsgroup-kill-file newsgroup)))
     (gnus-make-directory (file-name-directory file))
@@ -9194,10 +9392,8 @@ If NEWSGROUP is nil, the global score file is selected."
             (bury-buffer gnus-article-buffer)
             (switch-to-buffer buffer))
            (t                          ;No good rules.
-            (find-file-other-window file))
-           ))
-    (gnus-kill-file-mode)
-    ))
+            (find-file-other-window file))))
+    (gnus-kill-file-mode)))
 
 ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>.
 (defun gnus-kill-set-kill-buffer ()
@@ -9216,252 +9412,74 @@ If NEWSGROUP is nil, the global score file is selected."
            (and (buffer-modified-p) (save-buffer))
            (kill-buffer (current-buffer)))))))
 
-(defun gnus-article-fetch-field (field)
-  (save-excursion
-    (set-buffer gnus-article-buffer)
-    (save-restriction
-      (widen)
-      (goto-char 1)
-      (narrow-to-region 1 (save-excursion 
-                           (search-forward "\n\n" nil t) (point)))
-      (goto-char 1)
-      (prog1
-         (mail-fetch-field field)
-       (widen)))))
-
-(defun gnus-kill-file-enter-kill (field regexp level date edit)
-  ;; Enter score file entry.
-  ;; FIELD: String containing the name of the header field to score.
-  ;; REGEXP: The string to score.
-  ;; LEVEL: How much to raise the score by.
-  ;; DATE: A date string for expire score or nil for permanent kills.
-  ;; EDIT: Allow the user to edit REGEXP iff non-nil.
+(defun gnus-kill-file-enter-kill (field regexp)
+  ;; Enter kill file entry.
+  ;; FIELD: String containing the name of the header field to kill.
+  ;; REGEXP: The string to kill.
   (save-excursion
-    (gnus-kill-set-kill-buffer)
-    (goto-char (point-min))
-    (let ((regexp 
-          (if edit (read-string 
-                    (format "Add %d to articles with %s matching: " 
-                            level (downcase field))
-                    regexp)
-            regexp))
-         entry string kill beg)
-      (setq entry (if date (cons regexp date) regexp)
-           string (format "(gnus-raise %S (quote %S) %S)\n"
-                          field entry level))
-      (while (and (setq beg (point))
-                 (condition-case nil
-                     (setq kill (read (current-buffer)))
-                   (error nil))
-                 (or (not (eq (nth 0 kill) 'gnus-raise))
-                     (not (string= (downcase (nth 1 kill)) (downcase field)))
-                     (not (eq (nth 3 kill) level))))
-       (setq kill nil))
-      (if (not kill)
-         (progn
-           (goto-char (point-min))
-           (insert string))
-       (let ((list (nth 2 kill)))
-         (if (and (listp list) (eq 'quote (car list)))
-             (setq list (car (cdr list))))
-         (setcar 
-          (nthcdr 2 kill) 
-          (if (and (listp list) (listp (cdr list)))
-              (list 'quote (cons entry list))
-            (list 'quote (list entry list)))))
-       (delete-region beg (point))
-       (insert (gnus-pp-gnus-kill kill)))
-      (gnus-kill-file-apply-string string))
-    ;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>.
-    (or edit 
-       (message "Added kill file entry %s: %s" (downcase field) regexp))))
-    
-(defun gnus-kill-file-set-variable (symbol value)
-   ;; Set SYMBOL to VALUE in the score file.
-   (save-excursion
-     (gnus-kill-set-kill-buffer)
-     (goto-char (point-min))
-     (let ((string (format "(setq %S %S)\n" symbol value))
-          kill beg)
-       (while (and (setq beg (point))
-                  (condition-case nil
-                      (setq kill (read (current-buffer)))
-                    (error nil))
-                  (or (not (eq (nth 0 kill) 'setq))
-                      (not (eq (nth 1 kill) symbol))))
-        (setq kill nil))
-       (if (not kill)
-          (progn
-            (goto-char (point-min))
-            (insert string))
-        (delete-region beg (point))
-        (insert string)))))
+    (let (string)
+      (gnus-kill-set-kill-buffer)
+      (goto-char (point-max))
+      (insert (setq string (format "(gnus-kill %S %S)\n" field regexp)))
+      (gnus-kill-file-apply-string string))))
     
-(defun gnus-kill-file-set-expunge-below (level)
-   "Automatically expunge articles with score below LEVEL."
-   (interactive "P")
-   (setq level (if level
-                 (prefix-numeric-value level)
-               gnus-summary-default-score))
-   (if (eq major-mode 'gnus-summary-mode)
-       (progn
-        (gnus-score-set 'expunge level)
-        (gnus-score-set 'touched t))
-     (gnus-kill-file-set-variable 'expunge-below level))
-   (message "Set expunge below level to %d." level))
-
- (defun gnus-kill-file-set-mark-below (level)
-   "Automatically mark articles with score below LEVEL as read."
-   (interactive "P")
-   (setq level (if level
-                  (prefix-numeric-value level)
-                gnus-summary-default-score))
-   (if (eq major-mode 'gnus-summary-mode)
-       (progn
-        (gnus-score-set 'mark level)
-        (gnus-score-set 'touched t)
-        (gnus-summary-set-mark-below level))
-     (gnus-kill-file-set-variable 'mark-below level))
-   (message "Set mark below level to %d." level))
- (defun gnus-kill-file-temporarily-raise-by-subject (level &optional header)
-   "Temporarily raise score by LEVEL for current subject.
- See `gnus-kill-expiry-days'."
-   (interactive "p")
-   (gnus-kill-file-raise-by-subject level header (current-time-string)))
-  
- (defun gnus-kill-file-temporarily-raise-by-author (level &optional header)
-   "Temporarily raise score by LEVEL for current author.
- See `gnus-kill-expiry-days'."
-   (interactive "p")
-   (gnus-kill-file-raise-by-author level header (current-time-string)))
-  
- (defun gnus-kill-file-temporarily-raise-by-thread (level &optional header)
-   "Temporarily raise score by LEVEL for current thread.
- See `gnus-kill-expiry-days'."
-   (interactive "p")
-   (gnus-kill-file-enter-kill 
-    "References"
-    (regexp-quote (header-id (or header gnus-current-headers)))
-    level
-    (current-time-string)
-    nil))
-  
- (defun gnus-kill-file-temporarily-raise-by-xref (level &optional header)
-   "Insert temporary score commands for articles that have been crossposted.
- By default use the current crossposted groups.
- See `gnus-kill-expiry-days'."
-   (interactive "p")
-   (gnus-kill-file-raise-by-xref level header (current-time-string)))
-  
- (defun gnus-kill-file-raise-by-subject (level &optional header date)
-   "Raise score by LEVEL for current subject."
-   (interactive "p")
-   (gnus-kill-file-enter-kill
-    "Subject"
-    (regexp-quote 
-     (gnus-simplify-subject 
-      (header-subject (or header gnus-current-headers))))
-    level
-    date
-    t))
+(defun gnus-kill-file-kill-by-subject ()
+  "Kill by subject."
+  (interactive)
+  (gnus-kill-file-enter-kill
+   "Subject" 
+   (regexp-quote 
+    (gnus-simplify-subject (header-subject gnus-current-headers)))))
   
- (defun gnus-kill-file-raise-by-author (level &optional header date)
-   "Raise score by LEVEL for current author."
-   (interactive "p")
-   (gnus-kill-file-enter-kill
-    "From"
-    (regexp-quote (header-from (or header gnus-current-headers)))
-    level
-    date
-    t))
+(defun gnus-kill-file-kill-by-author ()
+  "Kill by author."
+  (interactive)
+  (gnus-kill-file-enter-kill
+   "From" (regexp-quote (header-from gnus-current-headers))))
  
- (defun gnus-kill-file-raise-by-xref (level &optional header date)
-   "Raise score by LEVEL for articles that have been crossposted.
- By default use the current crossposted groups."
-   (interactive "p")
-   (let ((xref (header-xref (or header gnus-current-headers)))
-        (start 0)
-        group)
-     (if xref
-        (while (string-match " \\([^ \t]+\\):" xref start)
-          (setq start (match-end 0))
-          (if (not (string= 
-                    (setq group 
-                          (substring xref (match-beginning 1) (match-end 1)))
-                    gnus-newsgroup-name))
-              (gnus-kill-file-enter-kill 
-               "Xref"
-               (concat " " (regexp-quote group) ":")
-               level
-               date
-               t))))))
-
-(defun gnus-kill-file-raise-followups-to-author
-  (level &optional header)
-  "Raise score for all followups to the current author."
+(defun gnus-kill-file-kill-by-thread ()
+  "Kill by author."
+  (interactive "p")
+  (gnus-kill-file-enter-kill
+   "References" (regexp-quote (header-id gnus-current-headers))))
+(defun gnus-kill-file-kill-by-xref ()
+  "Kill by Xref."
   (interactive)
-  (let ((name (header-from (or header gnus-current-headers)))
-       (string))
+  (let ((xref (header-xref gnus-current-headers))
+       (start 0)
+       group)
+    (if xref
+       (while (string-match " \\([^ \t]+\\):" xref start)
+         (setq start (match-end 0))
+         (if (not (string= 
+                   (setq group 
+                         (substring xref (match-beginning 1) (match-end 1)))
+                   gnus-newsgroup-name))
+             (gnus-kill-file-enter-kill 
+              "Xref" (concat " " (regexp-quote group) ":"))))
+      (gnus-kill-file-enter-kill "Xref" ""))))
+
+(defun gnus-kill-file-raise-followups-to-author (level)
+  "Raise score for all followups to the current author."
+  (interactive "p")
+  (let ((name (header-from gnus-current-headers))
+       string)
     (save-excursion
       (gnus-kill-set-kill-buffer)
       (goto-char (point-min))
       (setq name (read-string (concat "Add " level
                                      " to followup articles to: ")
                              (regexp-quote name)))
-      (setq string
-           (format "(gnus-kill %S %S '(gnus-summary-temporarily-raise-by-thread %S))\n"
-                   "From" name level))
+      (setq 
+       string
+       (format
+       "(gnus-kill %S %S '(gnus-summary-temporarily-raise-by-thread %S))\n"
+       "From" name level))
       (insert string)
       (gnus-kill-file-apply-string string))
     (message "Added permanent score file entry for followups to %s." name)))
 
-(defun gnus-kill-file-temporarily-lower-by-subject (level &optional header)
-  "Temporarily lower score by LEVEL for current subject.
-See `gnus-kill-expiry-days'."
-  (interactive "p")
-  (gnus-kill-file-lower-by-subject level header (current-time-string)))
-
-(defun gnus-kill-file-temporarily-lower-by-author (level &optional header)
-  "Temporarily lower score by LEVEL for current author.
-See `gnus-kill-expiry-days'."
-  (interactive "p")
-  (gnus-kill-file-lower-by-author level header (current-time-string)))
-
-(defun gnus-kill-file-temporarily-lower-by-thread (level &optional header)
-  "Temporarily lower score by LEVEL for current thread.
-See `gnus-kill-expiry-days'."
-  (interactive "p")
-  (gnus-kill-file-temporarily-raise-by-thread (- (gnus-score-default level)) header))
-
-(defun gnus-kill-file-temporarily-lower-by-xref (level &optional header)
-  "Insert temporary score commands for articles that have been crossposted.
-By default use the current crossposted groups.
-See `gnus-kill-expiry-days'."
-  (interactive "p")
-  (gnus-kill-file-lower-by-xref level header (current-time-string)))
-
-(defun gnus-kill-file-lower-by-subject (level &optional header date)
-    "Lower score by LEVEL for current subject."
-  (interactive "p")
-  (gnus-kill-file-raise-by-subject (- (gnus-score-default level)) header date))
-
-(defun gnus-kill-file-lower-by-author (level &optional header date)
-  "Lower score by LEVEL for current author."
-  (interactive "p")
-  (gnus-kill-file-raise-by-author (- (gnus-score-default level)) header date))
-
-(defun gnus-kill-file-lower-by-xref (level &optional header date)
-  "Lower score by LEVEL for articles that have been crossposted.
-By default use the current crossposted groups."
-  (gnus-kill-file-raise-by-xref (- (gnus-score-default level)) header date))
-
-(defun gnus-kill-file-lower-followups-to-author
-  (level &optional header)
-  "Lower score for all followups to the current author."
-  (interactive "p")
-  (gnus-kill-file-raise-followups-to-author (- (gnus-score-default level)) header))
-
 (defun gnus-kill-file-apply-buffer ()
   "Apply current buffer to current newsgroup."
   (interactive)
@@ -9474,7 +9492,7 @@ By default use the current crossposted groups."
 (defun gnus-kill-file-apply-string (string)
   "Apply STRING to current newsgroup."
   (interactive)
-  (let ((string (concat "(progn \n" string "\n)" )))
+  (let ((string (concat "(progn \n" string "\n)")))
     (save-excursion
       (save-window-excursion
        (pop-to-buffer gnus-summary-buffer)
@@ -9496,7 +9514,7 @@ By default use the current crossposted groups."
     (ding) (message "No newsgroup is selected.")))
 
 (defun gnus-kill-file-exit ()
-  "Save a score file, then return to the previous buffer."
+  "Save a kill file, then return to the previous buffer."
   (interactive)
   (save-buffer)
   (let ((killbuf (current-buffer)))
@@ -9514,11 +9532,12 @@ By default use the current crossposted groups."
 
 ;; Basic ideas by emv@math.lsa.umich.edu (Edward Vielmetti)
 
+;;;###autoload
 (defalias 'gnus-batch-kill 'gnus-batch-score)
 ;;;###autoload
 (defun gnus-batch-score ()
   "Run batched scoring.
-Usage: emacs -batch -l gnus -f gnus-batch-kill <newsgroups> ...
+Usage: emacs -batch -l gnus -f gnus-batch-score <newsgroups> ...
 Newsgroups is a list of strings in Bnews format.  If you want to score
 the comp hierarchy, you'd say \"comp.all\". If you would not like to
 score the alt hierarchy, you'd say \"!alt.all\"."
@@ -9560,14 +9579,14 @@ score the alt hierarchy, you'd say \"!alt.all\"."
     (switch-to-buffer gnus-group-buffer)
     (gnus-group-save-newsrc)))
 
-;; For score files
+;; For kill files
 
 (defun gnus-Newsgroup-kill-file (newsgroup)
-  "Return the name of a score file for NEWSGROUP.
-If NEWSGROUP is nil, return the global score file instead."
+  "Return the name of a kill file for NEWSGROUP.
+If NEWSGROUP is nil, return the global kill file instead."
   (cond ((or (null newsgroup)
             (string-equal newsgroup ""))
-        ;; The global score file is placed at top of the directory.
+        ;; The global kill file is placed at top of the directory.
         (expand-file-name gnus-kill-file-name
                           (or gnus-kill-files-directory "~/News")))
        (gnus-use-long-file-name
@@ -9579,12 +9598,11 @@ If NEWSGROUP is nil, return the global score file instead."
         ;; Place "KILL" under the hierarchical directory.
         (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
                                   "/" gnus-kill-file-name)
-                          (or gnus-kill-files-directory "~/News")))
-       ))
+                          (or gnus-kill-files-directory "~/News")))))
 
 (defun gnus-newsgroup-kill-file (newsgroup)
-  "Return the name of a score file name for NEWSGROUP.
-If NEWSGROUP is nil, return the global score file name instead."
+  "Return the name of a kill file name for NEWSGROUP.
+If NEWSGROUP is nil, return the global kill file name instead."
   (cond ((or (null newsgroup)
             (string-equal newsgroup ""))
         ;; The global KILL file is placed at top of the directory.
@@ -9598,20 +9616,18 @@ If NEWSGROUP is nil, return the global score file name instead."
         ;; Place "KILL" under the hierarchical directory.
         (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
                                   "/" gnus-kill-file-name)
-                          (or gnus-kill-files-directory "~/News")))
-       ))
-
+                          (or gnus-kill-files-directory "~/News")))))
 
 (defalias 'gnus-expunge 'gnus-summary-remove-lines-marked-with)
 
 (defun gnus-apply-kill-file ()
-  "Apply a score file to the current newsgroup.
+  "Apply a kill file to the current newsgroup.
 Returns the number of articles marked as read."
   (let* ((kill-files (list (gnus-newsgroup-kill-file nil)
                           (gnus-newsgroup-kill-file gnus-newsgroup-name)))
         (unreads (length gnus-newsgroup-unreads))
         (gnus-summary-inhibit-highlight t)
-        (mark-below (or gnus-summary-mark-below gnus-summary-default-score))
+        (mark-below (or gnus-summary-mark-below gnus-summary-default-score 0))
         (expunge-below gnus-summary-expunge-below)
         form beg)
     (setq gnus-newsgroup-kill-headers nil)
@@ -9659,13 +9675,12 @@ Returns the number of articles marked as read."
                        (progn
                          (delete-region beg (point))
                          (insert (or (eval form) "")))
-                     (eval form)))
+                     (condition-case ()
+                         (eval form)
+                       (error nil))))
                  (and (buffer-modified-p) (save-buffer))
                  (message "Processing kill file %s...done" (car kill-files))))
            (setq kill-files (cdr kill-files)))))
-    (if expunge-below (gnus-summary-expunge-below expunge-below))
-    (let (gnus-summary-inhibit-highlight)
-      (gnus-summary-set-mark-below mark-below))
     (if beg
        (let ((nunreads (- unreads (length gnus-newsgroup-unreads))))
          (or (eq nunreads 0)
@@ -9701,7 +9716,7 @@ COMMAND must be a lisp expression or a string representing a key sequence."
                (if (zerop (gnus-execute field (car kill-list) 
                                         command nil (not all)))
                    (if (> (gnus-days-between date (cdr kill-list))
-                          gnus-kill-expiry-days)
+                          gnus-score-expiry-days)
                        (setq regexp nil))
                  (setcdr kill-list date))
              (while (setq kill (car kill-list))
@@ -9712,7 +9727,7 @@ COMMAND must be a lisp expression or a string representing a key sequence."
                      (if (zerop (gnus-execute 
                                  field (car kill) command nil (not all)))
                          (if (> (gnus-days-between date kdate)
-                                gnus-kill-expiry-days)
+                                gnus-score-expiry-days)
                              ;; Time limit has been exceeded, so we
                              ;; remove the match.
                              (if prev
@@ -9724,9 +9739,8 @@ COMMAND must be a lisp expression or a string representing a key sequence."
                  (gnus-execute field kill command nil (not all)))
                (setq prev kill-list)
                (setq kill-list (cdr kill-list))))
-         (gnus-execute field kill-list command nil (not all)))
-       )))
-  (if regexp
+         (gnus-execute field kill-list command nil (not all))))))
+  (if (and (eq major-mode 'gnus-kill-file-mode) regexp)
       (gnus-pp-gnus-kill
        (nconc (list 'gnus-kill field 
                    (if (consp regexp) (list 'quote regexp) regexp))
@@ -9796,7 +9810,7 @@ COMMAND must be a lisp expression or a string representing a key sequence."
                  (setq did-kill (re-search-forward regexp nil t)))
                (if (stringp form)      ;Keyboard macro.
                    (execute-kbd-macro form)
-                 (funcall form))))))
+                 (eval form))))))
       did-kill)))
 
 (defun gnus-execute (field regexp form &optional backward ignore-marked)
@@ -9809,7 +9823,7 @@ marked as read or ticked are ignored."
     (let ((killed-no 0)
          function header article)
       (if (or (null field) (string-equal field ""))
-         (setq field nil)
+         (setq function nil)
        ;; Get access function of header filed.
        (setq function (intern-soft (concat "gnus-header-" (downcase field))))
        (if (and function (fboundp function))
@@ -9817,107 +9831,210 @@ marked as read or ticked are ignored."
          (error "Unknown header field: \"%s\"" field))
        ;; Make FORM funcallable.
        (if (and (listp form) (not (eq (car form) 'lambda)))
-           (setq form (list 'lambda nil form)))
-       ;; Starting from the current article.
-       (while (or (and (not article)
-                       (setq article (gnus-summary-article-number))
-                       t)
-                  (setq article 
-                        (gnus-summary-search-subject 
-                         backward (not ignore-marked))))
-         (and (memq article gnus-newsgroup-kill-headers)
-              (gnus-execute-1 function regexp form 
-                              (gnus-get-header-by-number article))
-              (setq killed-no (1+ killed-no)))))
+           (setq form (list 'lambda nil form))))
+      ;; Starting from the current article.
+      (while (or (and (not article)
+                     (setq article (gnus-summary-article-number))
+                     t)
+                (setq article 
+                      (gnus-summary-search-subject 
+                       backward (not ignore-marked))))
+       (and (or (null gnus-newsgroup-kill-headers)
+                (memq article gnus-newsgroup-kill-headers))
+            (gnus-execute-1 function regexp form 
+                            (gnus-get-header-by-number article))
+            (setq killed-no (1+ killed-no))))
       killed-no)))
 
 \f
-;;; Gnus Score File
+;;;
+;;; Gnus Score Files
+;;;
 
 ;; 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 
+   (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg))
+            (string-to-int (read-string "Mark below: ")))))
+  (setq score (or score gnus-summary-default-score 0))
+  (gnus-score-set 'mark (list score))
+  (gnus-score-set 'touched '(t))
+  (setq gnus-summary-mark-below score)
+  (gnus-summary-update-lines))
+
+(defun gnus-score-set-expunge-below (score)
+  "Automatically expunge articles with score below SCORE."
+  (interactive 
+   (list (or (and current-prefix-arg (prefix-numeric-value current-prefix-arg))
+            (string-to-int (read-string "Mark below: ")))))
+  (setq score (or score gnus-summary-default-score 0))
+  (gnus-score-set 'expunge (list score))
+  (gnus-score-set 'touched '(t)))
+
 (defun gnus-score-default (level)
   (if level (prefix-numeric-value level) 
     gnus-score-interactive-default-score))
 
 (defun gnus-score-set (symbol value &optional alist)
   ;; Set SYMBOL to VALUE in ALIST.
-  (let* ((local-score (gnus-score-file-name gnus-newsgroup-name))
-        (alist 
+  (let* ((alist 
          (or alist 
-             (setq gnus-score-alist 
-                   (cdr (assoc local-score gnus-score-cache)))
+             gnus-score-alist
              (progn
-               (gnus-score-load local-score)
+               (gnus-score-load (gnus-score-file-name gnus-newsgroup-name))
                gnus-score-alist)))
         (entry (assoc symbol alist)))
-    (cond (entry
+    (cond ((gnus-score-get 'read-only alist)
+          ;; This is a read-only score file, so we do nothing.
+          )
+         (entry
           (setcdr entry value))
          ((null alist)
           (error "Empty alist"))
          (t
-          (setcdr alist (cons (cons symbol value) (cdr alist)))))))
+          (setcdr alist
+                  (cons (cons symbol value) (cdr alist)))))))
 
 (defun gnus-score-get (symbol &optional alist)
   ;; Get SYMBOL's definition in ALIST.
   (cdr (assoc symbol 
              (or alist 
-;                (setq gnus-score-alist 
-;                      (cdr (assoc (gnus-score-file-name gnus-newsgroup-name)
-;                                  gnus-score-cache))
-                 
+                 gnus-score-alist
                  (progn
                    (gnus-score-load 
                     (gnus-score-file-name gnus-newsgroup-name))
                    gnus-score-alist)))))
 
-(defun gnus-score-edit-file (group)
-  "Edit score file for GROUP."
-  (interactive (list (read-string "Edit SCORE file for: "
-                                 (cons (or gnus-newsgroup-name "") 1))))
-  (and (get-buffer gnus-summary-buffer) (gnus-score-save))
-  (find-file (gnus-score-file-name group))
-  (emacs-lisp-mode))
-
+(defun gnus-score-change-score-file (file)
+  "Change current score alist."
+  (interactive
+   (list (completing-read "Score file: " gnus-score-cache)))
+  (setq gnus-current-score-file file)
+  (gnus-score-load-file file))
+
+(defun gnus-score-edit-file (file)
+  "Edit score file."
+  (interactive (list gnus-current-score-file))
+  (and (buffer-name gnus-summary-buffer) (gnus-score-save))
+  (setq gnus-winconf-edit-score (current-window-configuration))
+  (gnus-configure-windows 'article)
+  (pop-to-buffer (find-file-noselect file))
+  (message (substitute-command-keys 
+           "\\<gnus-score-mode-map>\\[gnus-score-edit-done] to save edits"))
+  (gnus-score-mode))
+  
 (defun gnus-score-load-file (file)
-  ;; Load score file FILE. Updates `gnus-scores-lists'.
-  (let ((cache (assoc file gnus-score-cache)))
-    (if cache
-       (progn
-         (setq gnus-score-alist (cdr cache))
-         (if (memq t (mapcar (lambda (e) (stringp (car e))) gnus-score-alist))
-             (setq gnus-scores-lists 
-                   (cons gnus-score-alist gnus-scores-lists))))
+  ;; Load score file FILE.  Returns a list a retrieved score-alists.
+  (let ((cached (assoc file gnus-score-cache))
+       (global (member file gnus-internal-global-score-files))
+       lists)
+    (if cached
+       ;; The score file was already loaded.
+       (setq gnus-score-alist (cdr cached))
+      ;; We load the score file.
       (setq gnus-score-alist nil)
-      (load file t nil t)
-      (if (memq t (mapcar (lambda (e) (stringp (car e))) gnus-score-alist))
-         (setq gnus-scores-lists (cons gnus-score-alist gnus-scores-lists)))
-      (or gnus-score-alist
-         (setq gnus-score-alist (copy-alist '((touched . nil)))))
+      (gnus-score-load-score-alist file)
+      ;; We add '(touched) to the alist to signify that it hasn't been
+      ;; touched (yet). 
+      (if (not (assq 'touched gnus-score-alist))
+         (setq gnus-score-alist 
+               (cons (list 'touched nil) gnus-score-alist)))
+      ;; If it is a global score file, we make it read-only.
+      (and global
+          (not (assq 'read-only gnus-score-alist))
+          (setq gnus-score-alist 
+                (cons (list 'read-only t) gnus-score-alist)))
+      ;; Update cache.
       (setq gnus-score-cache
-           (cons (cons file gnus-score-alist) gnus-score-cache))))
-  (let ((mark (gnus-score-get 'mark))
-       (expunge (gnus-score-get 'expunge))
-       (files (gnus-score-get 'files))
-       (eval (gnus-score-get 'eval)))
-    (if files (mapcar (lambda (file) (gnus-score-load-file file)) files))
-    (if eval (eval eval))
-    (if mark (setq gnus-summary-mark-below mark))
-    (if expunge (setq gnus-summary-expunge-below expunge))))
+           (cons (cons file gnus-score-alist) gnus-score-cache)))
+    ;; If there are actual scores in the alist, we add it to the
+    ;; return value of this function.
+    (if (memq t (mapcar (lambda (e) (stringp (car e))) gnus-score-alist))
+       (setq lists (list gnus-score-alist)))
+    ;; Treat the other possible atoms in the score alist.
+    (let ((mark (car (gnus-score-get 'mark gnus-score-alist)))
+         (expunge (car (gnus-score-get 'expunge gnus-score-alist)))
+         (mark-and-expunge 
+          (car (gnus-score-get 'mark-and-expunge gnus-score-alist)))
+         (read-only (gnus-score-get 'read-only gnus-score-alist))
+         (files (gnus-score-get 'files gnus-score-alist))
+         (eval (gnus-score-get 'eval gnus-score-alist)))
+      ;; We do not respect eval and files atoms from global score
+      ;; files. 
+      (and files (not global)
+          (setq lists (apply 'append lists
+                             (mapcar (lambda (file)
+                                       (gnus-score-load-file file)) 
+                                     files))))
+      (and eval (not global) (eval eval))
+      (setq gnus-summary-mark-below (or mark mark-and-expunge 
+                                       gnus-summary-default-score))
+      (setq gnus-summary-expunge-below (or expunge mark-and-expunge)))
+    (setq gnus-current-score-file file)
+    lists))
 
 (defun gnus-score-load (file)
   ;; Load score FILE.
-  ;; Updates free variables `gnus-score-alist' and `scores'.
-
   (let ((cache (assoc file gnus-score-cache)))
     (if cache
        (setq gnus-score-alist (cdr cache))
       (setq gnus-score-alist nil)
-      (load file t nil t)
+      (gnus-score-load-score-alist file)
       (or gnus-score-alist
          (setq gnus-score-alist (copy-alist '((touched . nil)))))
       (setq gnus-score-cache
            (cons (cons file gnus-score-alist) gnus-score-cache)))))
+
+(defun gnus-score-remove-from-cache (file)
+  (setq gnus-score-cache (delq (assoc file gnus-score-cache)
+                              gnus-score-cache)))
+
+(defun gnus-score-load-score-alist (file)
+  (let (alist)
+    (if (file-readable-p file)
+       (progn
+         (save-excursion
+           (set-buffer (get-buffer-create " *gnus work*"))
+           (buffer-disable-undo (current-buffer))
+           (erase-buffer)
+           (insert-file-contents file)
+           (goto-char (point-min))
+           (setq alist
+                 (condition-case ()
+                     (read (current-buffer))
+                   (error 
+                    (progn
+                      (message "Problem with score file %s" file)
+                      (ding) 
+                      nil)))))
+         (if (eq (car alist) 'setq)
+             (setq gnus-score-alist
+                   (gnus-score-transform-old-to-new alist))
+           (setq gnus-score-alist alist))))))
+
+(defun gnus-score-transform-old-to-new (alist)
+  (let* ((alist (nth 2 alist))
+        out entry)
+    (if (eq (car alist) 'quote)
+       (setq alist (nth 1 alist)))
+    (while alist
+      (setq entry (car alist))
+      (if (stringp (car entry))
+         (let ((scor (cdr entry)))
+           (setq out (cons entry out))
+           (while scor
+             (setcar scor
+                     (list (car (car scor)) (nth 2 (car scor))
+                           (and (nth 3 (car scor))
+                                (gnus-day-number (nth 3 (car scor))))
+                           (if (nth 1 (car scor)) 'r 's)))
+             (setq scor (cdr scor))))
+       (setq out (cons (list (car entry) (cdr entry)) out)))
+      (setq alist (cdr alist)))
+    (cons (list 'touched t) (nreverse out))))
   
 (defun gnus-score-save ()
   ;; Save all SCORE information.
@@ -9936,38 +10053,37 @@ marked as read or ticked are ignored."
                cache (cdr cache)
                file (car entry)
                score (cdr entry))
-         (if (null (gnus-score-get 'touched score))
+         (if (or (not (eq (gnus-score-get 'touched score) '(t)))
+                 (gnus-score-get 'read-only score)
+                 (not (file-writable-p file)))
              ()
-           (gnus-score-set 'touched nil score)
+           (setq score (delq (assq 'touched score) score))
            (erase-buffer)
            (let (emacs-lisp-mode-hook)
-             (pp (list 'setq 'gnus-score-alist (list 'quote score))
-                 (current-buffer)))
+             (pp score (current-buffer)))
            (make-directory (file-name-directory file) t)
-             (write-region (point-min) (point-max) file nil 'silent))))
+           (write-region (point-min) (point-max) file nil 'silent))))
       (kill-buffer (current-buffer)))))
   
 (defun gnus-score-headers ()
   ;; Score `gnus-newsgroup-headers'.
-  (let ((score-files (and gnus-score-find-score-files-function
+  (let ((score-files (and (symbolp gnus-score-find-score-files-function)
                          (fboundp gnus-score-find-score-files-function)
                          (funcall gnus-score-find-score-files-function
                                   gnus-newsgroup-name)))
        scores)
     ;; Load the SCORE files.
     (while score-files
-      (gnus-score-load-file (car score-files))
+      (setq scores (nconc (gnus-score-load-file (car score-files)) scores))
       (setq score-files (cdr score-files)))
-    (setq scores gnus-scores-lists
-         gnus-scores-lists nil)
     (if (not (and gnus-summary-default-score
                  scores
                  (> (length gnus-newsgroup-headers)
                     (length gnus-newsgroup-scored))))
        ()
       (let* ((entries gnus-header-index)
-            (now (current-time-string))
-            (expire (- (gnus-useful-date now) gnus-kill-expiry-days))
+            (now (gnus-day-number (current-time-string)))
+            (expire (- now gnus-score-expiry-days))
             (headers gnus-newsgroup-headers)
             entry header)
        (message "Scoring...")
@@ -9980,7 +10096,7 @@ marked as read or ticked are ignored."
          ;; and S is (length gnus-newsgroup-scored).
          (or (assq (header-number header) gnus-newsgroup-scored)
              (setq gnus-scores-articles       ;Total of 2 * N cons-cells used.
-                   (cons (cons header gnus-summary-default-score)
+                   (cons (cons header (or gnus-summary-default-score 0))
                          gnus-scores-articles))))
   
        (save-excursion
@@ -10000,7 +10116,6 @@ marked as read or ticked are ignored."
          ;; Remove the buffer.
          (kill-buffer (current-buffer)))
 
-       (message "Scoring...")
        ;; Add articles to `gnus-newsgroup-scored'.
        (while gnus-scores-articles
          (or (= gnus-summary-default-score (cdr (car gnus-scores-articles)))
@@ -10013,11 +10128,11 @@ marked as read or ticked are ignored."
 
        (message "Scoring...done")))))
 
-;(defun gnus-score-integer (scores header now expire)
-;  )
+;;(defun gnus-score-integer (scores header now expire)
+;;  )
 
-;(defun gnus-score-date (scores header now expire)
-;  )
+;;(defun gnus-score-date (scores header now expire)
+;;  )
 
 (defun gnus-score-string (scores header now expire)
   ;; Score ARTICLES according to HEADER in SCORES.
@@ -10070,16 +10185,17 @@ marked as read or ticked are ignored."
        (let* ((rest (cdr entries))             
               (kill (car rest))
               (match (nth 0 kill))
-              (type (nth 1 kill))
-              (score (nth 2 kill))
-              (date (nth 3 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 t)
               arts art)
          (goto-char (point-min))
-         (while (if type
-                    (re-search-forward match nil t)
-                  (search-forward match nil t))
+         (while (cond ((eq type 'r)
+                       (re-search-forward match nil t))
+                      ((eq type 's)
+                       (search-forward match nil t)))
            (end-of-line 1)
            (setq found t
                  arts (get-text-property (point) 'articles))
@@ -10091,10 +10207,10 @@ marked as read or ticked are ignored."
          ;; Update expire date
          (cond ((null date))           ;Permanent entry.
                (found                  ;Match, update date.
-                (gnus-score-set 'touched t alist)
-                (setcar (nthcdr 3 kill) now))
-               ((< (gnus-useful-date date) expire) ;Old entry, remove.
-                (gnus-score-set 'touched t alist)
+                (gnus-score-set 'touched '(t) alist)
+                (setcar (nthcdr 2 kill) now))
+               ((< date expire) ;Old entry, remove.
+                (gnus-score-set 'touched '(t) alist)
                 (setcdr entries (cdr rest))
                 (setq rest entries)))
          (setq entries rest))))))
@@ -10105,12 +10221,6 @@ marked as read or ticked are ignored."
   (string-lessp (aref (car a1) gnus-score-index)
                (aref (car a2) gnus-score-index)))
 
-(defun gnus-useful-date (date)
-  ;; Return the numeric day corresponding to the DATE string.
-  (let ((d (mapcar (lambda (s) (and s (string-to-int s)) )
-                  (timezone-parse-date date))))
-    (timezone-absolute-from-gregorian (nth 1 d) (nth 2 d) (car d))))
-
 (defun gnus-score-build-cons (article)
   ;; Build a `gnus-newsgroup-scored' type cons from ARTICLE.
   (cons (header-number (car article)) (cdr article)))
@@ -10121,15 +10231,12 @@ marked as read or ticked are ignored."
     ("subject" 1 gnus-score-string)
     ("from" 2 gnus-score-string)
     ("date" 3 gnus-score-date)
-    ("id" 4 gnus-score-string) 
+    ("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)))
 
-(defvar gnus-score-file-suffix "SCORE"
-  "Suffix of the score files.")
-
 (defun gnus-score-file-name (newsgroup)
   "Return the name of a score file for NEWSGROUP."
   (cond  ((or (null newsgroup)
@@ -10142,25 +10249,31 @@ marked as read or ticked are ignored."
          (expand-file-name (concat newsgroup "." gnus-score-file-suffix)
                            (or gnus-kill-files-directory "~/News")))
         (t
-         ;; Place "KILL" under the hierarchical directory.
+         ;; Place "SCORE" under the hierarchical directory.
          (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
                                    "/" gnus-score-file-suffix)
                            (or gnus-kill-files-directory "~/News")))))
 
 (defun gnus-score-score-files (group)
   "Return a list of all possible score files."
-  (or gnus-kill-files-directory (setq gnus-kill-files-directory "~/News/"))
-  (if (not (file-exists-p gnus-kill-files-directory))
+  (and gnus-global-score-files 
+       (or gnus-internal-global-score-files
+          (gnus-score-search-global-directories gnus-global-score-files)))
+  (setq gnus-kill-files-directory 
+       (file-name-as-directory
+        (or gnus-kill-files-directory "~/News/")))
+  (if (not (file-readable-p gnus-kill-files-directory))
       (setq gnus-score-file-list nil)
     (if gnus-use-long-file-name
        (if (or (not gnus-score-file-list)
                (gnus-file-newer-than gnus-kill-files-directory
                                      (car gnus-score-file-list)))
-           (setq gnus-score-file-list
-                 (cons (nth 5 (file-attributes gnus-kill-files-directory))
-                       (directory-files
-                        gnus-kill-files-directory t
-                        (concat gnus-score-file-suffix "$")))))
+             (setq gnus-score-file-list 
+                   (cons (nth 5 (file-attributes gnus-kill-files-directory))
+                         (nreverse 
+                          (directory-files 
+                           gnus-kill-files-directory t
+                           (concat gnus-score-file-suffix "$"))))))
       (let ((dir (expand-file-name
                  (concat gnus-kill-files-directory
                          (gnus-replace-chars-in-string group ?. ?/))))
@@ -10173,9 +10286,10 @@ marked as read or ticked are ignored."
               (setq files (cons (concat dir "/all/" gnus-score-file-suffix)
                                 files)))
          (string-match "/[^/]*$" dir)
-         (setq dir (substring dir (match-beginning 0))))
-       (setq gnus-score-file-list (cons nil files)))))
-  (cdr gnus-score-file-list))
+         (setq dir (substring dir 0 (match-beginning 0))))
+       (setq gnus-score-file-list 
+             (cons nil (nreverse files)))))
+    (cdr gnus-score-file-list)))
        
 (defun gnus-score-find-single (group)
   "Return list containing the score file for GROUP."
@@ -10196,29 +10310,46 @@ This includes the score file for the group and all its parents."
   "Return a list of score files for GROUP.
 The score files are those files in the ~/News directory which matches
 GROUP using BNews sys file syntax."
-  (let ((sfiles (gnus-score-score-files group))
-       (klen (length (expand-file-name gnus-kill-files-directory)))
-       ofiles not-match regexp)
+  (let* ((sfiles (append (gnus-score-score-files group)
+                        gnus-internal-global-score-files))
+        (kill-dir (file-name-as-directory 
+                   (expand-file-name gnus-kill-files-directory)))
+        (klen (length kill-dir))
+        ofiles not-match regexp)
     (save-excursion
       (set-buffer (get-buffer-create "*gnus score files*"))
       (buffer-disable-undo (current-buffer))
+      ;; Go through all score file names and create regexp with them
+      ;; as the source.  
       (while sfiles
        (erase-buffer)
        (insert (car sfiles))
        (goto-char 1)
+       ;; First remove the suffix itself.
        (re-search-forward (concat "." gnus-score-file-suffix "$"))
        (replace-match "") 
        (goto-char 1)
-       (delete-char klen)
+       (if (looking-at (regexp-quote kill-dir))
+           ;; If the file name was just "SCORE", `klen' is one character
+           ;; too much.
+           (delete-char (min (1- (point-max)) klen))
+         (goto-char (point-max))
+         (search-backward "/")
+         (delete-region (1+ (point)) (point-min)))
+       ;; Translate "all" to ".*".
        (while (search-forward "all" nil t)
-         (replace-match ".+"))
+         (replace-match ".*"))
        (goto-char 1)
+       ;; Deal with "not."s.
        (if (looking-at "not.")
            (progn
              (setq not-match t)
              (setq regexp (buffer-substring 5 (point-max))))
          (setq regexp (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.
        (if (or (and not-match
                     (not (string-match regexp group)))
                (and (not not-match)
@@ -10226,10 +10357,83 @@ GROUP using BNews sys file syntax."
            (setq ofiles (cons (car sfiles) ofiles)))
        (setq sfiles (cdr sfiles)))
       (kill-buffer (current-buffer))
-      ofiles)))
+      ;; 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
+      ;; file, and not end up in some global score file.
+      (let ((localscore
+            (expand-file-name
+             (if gnus-use-long-file-name
+                 (concat gnus-kill-files-directory group "." 
+                         gnus-score-file-suffix)
+               (concat gnus-kill-files-directory
+                       (gnus-replace-chars-in-string group ?. ?/)
+                       "/" gnus-score-file-suffix)))))
+       (and (member localscore ofiles)
+            (delete localscore ofiles))
+       (setq ofiles (cons localscore ofiles)))
+      (nreverse ofiles))))
+
+(defun gnus-score-search-global-directories (files)
+  "Scan all global score directories for score files."
+  ;; Set the variable `gnus-internal-global-score-files' to all
+  ;; available global score files.
+  (interactive (list gnus-global-score-files))
+  (let (out)
+    (while files
+      (if (string-match "/$" (car files))
+         (setq out (nconc (directory-files 
+                           (car files) t
+                           (concat gnus-score-file-suffix "$"))))
+       (setq out (cons (car files) out)))
+      (setq files (cdr files)))
+    (setq gnus-internal-global-score-files out)))
+
+;;;
+;;; Score mode.
+;;;
+
+(defvar gnus-score-mode-map nil)
+(defvar gnus-score-mode-hook nil)
+
+(if gnus-score-mode-map
+    ()
+  (setq gnus-score-mode-map (copy-keymap emacs-lisp-mode-map))
+  (define-key gnus-score-mode-map "\C-c\C-c" 'gnus-score-edit-done)
+  (define-key gnus-score-mode-map "\C-c\C-d" 'gnus-score-edit-insert-date))
+
+(defun gnus-score-mode ()
+  "Mode for editing score files.
+This mode is an extended emacs-lisp mode.
 
+\\{gnus-score-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+  (use-local-map gnus-score-mode-map)
+  (set-syntax-table emacs-lisp-mode-syntax-table)
+  (setq major-mode 'gnus-score-mode)
+  (setq mode-name "Score")
+  (lisp-mode-variables nil)
+  (run-hooks 'emacs-lisp-mode-hook 'gnus-score-mode-hook))
+
+(defun gnus-score-edit-insert-date ()
+  "Insert date in numerical format."
+  (interactive)
+  (insert (int-to-string (gnus-day-number (current-time-string)))))
+
+(defun gnus-score-edit-done ()
+  "Save the score file and return to the summary buffer."
+  (interactive)
+  (let ((bufnam (buffer-file-name (current-buffer))))
+    (save-buffer)
+    (kill-buffer (current-buffer))
+    (and gnus-winconf-edit-score
+        (set-window-configuration gnus-winconf-edit-score))
+    (gnus-score-remove-from-cache bufnam)
+    (gnus-score-load-file bufnam)))
 
 \f
+;;;
 ;;; Gnus Posting Functions
 ;;;
 
@@ -10239,8 +10443,6 @@ GROUP using BNews sys file syntax."
 (defvar gnus-post-news-buffer "*post-news*")
 (defvar gnus-winconf-post-news nil)
 
-(autoload 'news-reply-mode "rnewspost")
-
 ;;; Post news commands of Gnus group mode and summary mode
 
 (defun gnus-group-post-news ()
@@ -10252,7 +10454,7 @@ GROUP using BNews sys file syntax."
   ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>.
   (or gnus-newsgroup-name (setq gnus-newsgroup-name (gnus-group-group-name)))
   (unwind-protect
-      (gnus-post-news 'post nil)
+      (gnus-post-news 'post)
     (or (and (eq (current-buffer) (get-buffer gnus-post-news-buffer))
             (not (zerop (buffer-size))))
        ;; Restore last window configuration.
@@ -10287,7 +10489,8 @@ GROUP using BNews sys file syntax."
 If prefix argument YANK is non-nil, original article is yanked automatically."
   (interactive "P")
   (gnus-set-global-variables)
-  (gnus-summary-select-article t)
+  (save-window-excursion
+    (gnus-summary-select-article t))
   (let ((headers gnus-current-headers)
        (gnus-newsgroup-name gnus-newsgroup-name))
     ;; Check Followup-To: poster.
@@ -10302,7 +10505,8 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
       ;; Save window configuration.
       (setq gnus-winconf-post-news (current-window-configuration))
       (unwind-protect
-         (gnus-post-news 'followup headers gnus-article-buffer yank)
+         (gnus-post-news nil gnus-newsgroup-name
+                         headers gnus-article-buffer yank)
        (or (and (eq (current-buffer) (get-buffer gnus-post-news-buffer))
                 (not (zerop (buffer-size))))
            ;; Restore last window configuration.
@@ -10370,18 +10574,16 @@ header line with the old Message-ID."
        (insert mail-header-separator))))
 
 \f
-;;; Post a News using NNTP
-
 ;;;###autoload
 (fset 'sendnews 'gnus-post-news)
 
 ;;;###autoload
 (fset 'postnews 'gnus-post-news)
 
-(defun gnus-post-news (method &optional header article-buffer yank)
+(defun gnus-post-news (post &optional group header article-buffer yank)
   "Begin editing a new USENET news article to be posted.
 Type \\[describe-mode] in the buffer to get a list of commands."
-  (interactive)
+  (interactive (list t))
   (if (or (not gnus-novice-user)
          gnus-expert-user
          (not (eq 'post 
@@ -10389,63 +10591,92 @@ Type \\[describe-mode] in the buffer to get a list of commands."
                           (format "%s" (car (gnus-find-method-for-group 
                                              gnus-newsgroup-name)))
                           gnus-valid-select-methods))))
+         (assq 'to-address (gnus-find-method-for-group gnus-newsgroup-name))
          (gnus-y-or-n-p "Are you sure you want to post to all of USENET? "))
-      (let ((sumart (if (eq method 'followup)
+      (let ((sumart (if (not post)
                        (save-excursion
                          (set-buffer gnus-summary-buffer)
                          (cons (current-buffer) gnus-current-article))))
-           post-buf)
-       (if (and gnus-interactive-post
-                (not gnus-expert-user)
-                (eq method 'post)
-                (not header))
-           (setq header 
-                 (completing-read "Group: " gnus-active-hashtb nil t)))
+           (from (and header (header-from header)))
+           subject follow-to real-group)
+       (and gnus-interactive-post
+            (not gnus-expert-user)
+            post (not group)
+            (progn
+              (setq group 
+                    (completing-read "Group: " gnus-active-hashtb nil t))
+              (setq subject (read-string "Subject: "))))
        (setq mail-reply-buffer article-buffer)
+
+       (setq real-group (gnus-group-real-name group))
        (setq gnus-post-news-buffer 
-             (setq post-buf
-                   (gnus-request-post-buffer 
-                    method (if (stringp header) 
-                               (gnus-group-real-name header) header)
-                    article-buffer)))
-       (if (eq method 'post)
+             (gnus-request-post-buffer 
+              post real-group subject header article-buffer
+              (nth 2 (gnus-gethash group gnus-newsrc-hashtb))
+              (if (and (boundp 'gnus-followup-to-function)
+                       gnus-followup-to-function)
+                  (setq follow-to
+                        (save-excursion
+                          (set-buffer article-buffer)
+                          (funcall gnus-followup-to-function group))))
+              (eq gnus-use-followup-to t)))
+       (if post
            (progn
-             (delete-other-windows)
-             (switch-to-buffer post-buf))
-         (delete-other-windows)
+             (gnus-configure-windows '(1 0 0))
+             (switch-to-buffer gnus-post-news-buffer))
+         (gnus-configure-windows '(0 1 0))
          (if (not yank)
              (progn
                (switch-to-buffer article-buffer)
-               (pop-to-buffer post-buf))
-           (switch-to-buffer post-buf)))
+               (pop-to-buffer gnus-post-news-buffer))
+           (switch-to-buffer gnus-post-news-buffer)))
        (gnus-overload-functions)
        (make-local-variable 'gnus-article-reply)
        (make-local-variable 'gnus-article-check-size)
        (setq gnus-article-reply sumart)
+       ;; Handle `gnus-auto-mail-to-author'.
+       ;; Suggested by Daniel Quinlan <quinlan@best.com>.
+       (let ((to (if (eq gnus-auto-mail-to-author 'ask)
+                     (and (y-or-n-p "Also send mail to author? ") from)
+                   (and gnus-auto-mail-to-author from))))
+         (if to
+             (progn
+               (if (mail-fetch-field "To")
+                   (progn
+                     (beginning-of-line)
+                     (insert "Cc: " to "\n"))
+                 (mail-position-on-field "To")
+                 (insert to)))))
        ;; Handle author copy using BCC field.
        (if (and gnus-mail-self-blind
                 (not (mail-fetch-field "bcc")))
            (progn
-             (mail-position-on-field "BCC")
+             (mail-position-on-field "Bcc")
              (insert (if (stringp gnus-mail-self-blind)
                          gnus-mail-self-blind
                        (user-login-name)))))
        ;; Handle author copy using FCC field.
        (if gnus-author-copy
            (progn
-             (mail-position-on-field "FCC")
+             (mail-position-on-field "Fcc")
              (insert gnus-author-copy)))
        (goto-char (point-min))
-       (if (and (eq method 'post) (not header))
-           (end-of-line)
+       (if post 
+           (cond ((not group)
+                  (re-search-forward "^Newsgroup:" nil t)
+                  (end-of-line))
+                 ((not subject)
+                  (re-search-forward "^Subject:" nil t)
+                  (end-of-line))
+                 (t
+                  (search-forward (concat "\n" mail-header-separator "\n"))))
          (search-forward (concat "\n" mail-header-separator "\n"))
          (if yank 
              (save-excursion
                (run-hooks 'news-reply-header-hook)
                (mail-yank-original nil)))
          (if gnus-post-prepare-function
-             (funcall gnus-post-prepare-function 
-                      (if (stringp header) header gnus-newsgroup-name))))))
+             (funcall gnus-post-prepare-function group)))))
   (setq gnus-article-check-size (cons (buffer-size) (gnus-article-checksum)))
   (message "")
   t)
@@ -10538,18 +10769,31 @@ will attempt to use the foreign server to post the article."
                  (mail-fetch-field "bcc" nil t)
                  (mail-fetch-field "cc" nil t))
              (if gnus-mail-send-method
-                 (progn
-                   (message "Sending via mail...")
-                   (widen)
-                   (funcall gnus-mail-send-method)
-                   (message "Sending via mail... done")
-                   (save-excursion
-                     (save-restriction
-                       (goto-char 1)
-                       (narrow-to-region
-                        1 (re-search-forward mail-header-separator))
-                       (goto-char 1)
-                       (delete-matching-lines "BCC:.*"))))
+                 (save-excursion
+                   (save-restriction
+                     (widen)
+                     (message "Sending via mail...")
+                     
+                     (if gnus-mail-courtesy-message
+                         (progn
+                           ;; Insert "courtesy" mail message.
+                           (goto-char 1)
+                           (re-search-forward mail-header-separator)
+                           (forward-line 1)
+                           (insert gnus-mail-courtesy-message)
+                           (funcall gnus-mail-send-method)
+                           (goto-char 1)
+                           (search-forward gnus-mail-courtesy-message)
+                           (replace-match ""))
+                       (funcall gnus-mail-send-method))
+
+                     (message "Sending via mail... done")
+                     
+                     (goto-char 1)
+                     (narrow-to-region
+                      1 (re-search-forward mail-header-separator))
+                     (goto-char 1)
+                     (delete-matching-lines "BCC:.*")))
                (ding)
                (message "No mailer defined.  To: and/or Cc: fields ignored.")
                (sit-for 1))))
@@ -10928,8 +11172,7 @@ a program specified by the rest of the value."
                   ;; Suggested by yuki@flab.fujitsu.junet.
                   ;; Send article to named program.
                   (call-process-region (point-min) (point-max) shell-file-name
-                                       nil nil nil "-c" program)
-                  ))
+                                       nil nil nil "-c" program)))
                (t
                 ;; Suggested by hyoko@flab.fujitsu.junet.
                 ;; Save article in Unix mail format by default.
@@ -10938,11 +11181,7 @@ a program specified by the rest of the value."
                     (funcall gnus-author-copy-saver fcc-file)
                   (if (and (file-readable-p fcc-file) (rmail-file-p fcc-file))
                       (gnus-output-to-rmail fcc-file)
-                    (rmail-output fcc-file 1 t t)))
-                ))
-         )
-       ))
-    ))
+                    (rmail-output fcc-file 1 t t))))))))))
 
 (defun gnus-inews-path ()
   "Return uucp path."
@@ -10952,8 +11191,7 @@ a program specified by the rest of the value."
          ((stringp gnus-use-generic-path)
           ;; Support GENERICPATH.  Suggested by vixie@decwrl.dec.com.
           (concat gnus-use-generic-path "!" login-name))
-         (t login-name))
-    ))
+         (t login-name))))
 
 (defun gnus-inews-user-name ()
   "Return user's network address as \"NAME@DOMAIN (FULL-NAME)\"."
@@ -10985,18 +11223,19 @@ name; if it is non-nil, strip off local host name from the domain name.
 If the function `system-name' returns full internet name and the
 domain is undefined, the domain name is got from it."
   (if (or genericfrom gnus-local-domain (getenv "DOMAINNAME"))
-      (let ((domain 
-            (or (if (stringp genericfrom) genericfrom)
-                (getenv "DOMAINNAME")
-                gnus-local-domain
-                ;; Function `system-name' may return full internet name.
-                ;; Suggested by Mike DeCorte <mrd@sun.soe.clarkson.edu>.
-                (if (string-match "\\." (system-name))
-                    (substring (system-name) (match-end 0)))
-                (read-string "Domain name (no host): ")))
-           (host (or (if (string-match "\\." (system-name))
-                         (substring (system-name) 0 (match-beginning 0)))
-                     (system-name))))
+      (let* ((system-name (system-name))
+            (domain 
+             (or (if (stringp genericfrom) genericfrom)
+                 (getenv "DOMAINNAME")
+                 gnus-local-domain
+                 ;; Function `system-name' may return full internet name.
+                 ;; Suggested by Mike DeCorte <mrd@sun.soe.clarkson.edu>.
+                 (if (string-match "\\." system-name)
+                     (substring system-name (match-end 0)))
+                 (read-string "Domain name (no host): ")))
+            (host (or (if (string-match "\\." system-name)
+                          (substring system-name 0 (match-beginning 0)))
+                      system-name)))
        (if (string-equal "." (substring domain 0 1))
            (setq domain (substring domain 1)))
        ;; Support GENERICFROM as same as standard Bnews system.
@@ -11005,7 +11244,10 @@ domain is undefined, the domain name is got from it."
               (concat host "." domain))
              ;;((stringp genericfrom) genericfrom)
              (t domain)))
-    (substring user-mail-address (1+ (string-match "@" user-mail-address)))))
+    (if (string-match "\\." (system-name))
+       (system-name)
+      (substring user-mail-address 
+                (1+ (string-match "@" user-mail-address))))))
 
 (defun gnus-inews-full-address ()
   (let ((domain (gnus-inews-domain-name))
@@ -11030,7 +11272,8 @@ domain is undefined, the domain name is got from it."
 
 (defun gnus-inews-date ()
   "Current time string."
-  (timezone-make-date-arpa-standard (current-time-string)))
+  (timezone-make-date-arpa-standard 
+   (current-time-string) (current-time-zone)))
 
 (defun gnus-inews-organization ()
   "Return user's organization.
@@ -11080,9 +11323,6 @@ organization."
 ;;; Gnus Mail Functions 
 ;;;
 
-(autoload 'news-mail-reply "rnewspost")
-(autoload 'news-mail-other-window "rnewspost")
-
 ;;; Mail reply commands of Gnus summary mode
 
 (defun gnus-summary-reply (yank)
@@ -11135,6 +11375,7 @@ mailer."
       (mail-mode)
       (make-local-variable 'gnus-article-reply)
       (setq gnus-article-reply cur)
+      (use-local-map (copy-keymap mail-mode-map))
       (local-set-key "\C-c\C-c" 'gnus-mail-send-and-exit)
       (if (and (buffer-modified-p)
               (> (buffer-size) 0)
@@ -11197,10 +11438,9 @@ mailer."
              (goto-char last))))
       (if (not yank)
          (let ((mail (current-buffer)))
-           (switch-to-buffer gnus-article-buffer)
-           (delete-other-windows)
+           (gnus-configure-windows '(0 0 1))
            (switch-to-buffer-other-window mail))
-       (delete-other-windows)
+       (gnus-configure-windows '(0 1 0))
        (switch-to-buffer (current-buffer))))))
 
 (defun gnus-mail-yank-original ()
@@ -11245,6 +11485,8 @@ mailer."
            (mail nil nil subject)
          (mail-other-window nil nil subject))
        (save-excursion
+         (use-local-map (copy-keymap emacs-lisp-mode-map))
+         (local-set-key "\C-c\C-c" 'gnus-mail-send-and-exit)
          (setq beg (goto-char (point-max)))
          (insert "------- Start of forwarded message -------\n")
          (insert-buffer forward-buffer)
@@ -11262,8 +11504,9 @@ mailer."
 
 (defun gnus-mail-other-window-using-mail ()
   "Compose mail other window using mail."
-  (news-mail-other-window)
-  (gnus-overload-functions))
+  (mail-other-window nil nil nil nil nil nil (get-buffer gnus-article-buffer))
+  (use-local-map (copy-keymap emacs-lisp-mode-map))
+  (local-set-key "\C-c\C-c" 'gnus-mail-send-and-exit))
 
 \f
 ;;;
@@ -11355,6 +11598,119 @@ mailer."
 ;;; Server Communication
 ;;;
 
+;; All the Gnus backends have the same interface, and should return
+;; data in a similar format. Below is an overview of what functions
+;; these packages must supply and what results they should return.
+;;
+;; Variables:
+;;
+;; `nntp-server-buffer' - All data should be returned to Gnus in this
+;; buffer. 
+;;
+;; Functions for the imaginary backend `choke':
+;;
+;; `choke-retrieve-headers ARTICLES &optional GROUP SERVER'
+;; Should return all headers for all ARTICLES, or return NOV lines for
+;; the same.
+;;
+;; `choke-request-group GROUP &optional SERVER DISCARD'
+;; Switch to GROUP. If DISCARD is nil, active information on the group
+;; must be returned.
+;;
+;; `choke-close-group GROUP &optional SERVER'
+;; Close group. Most backends won't have to do anything with this
+;; call, but it is an opportunity to clean up, if that is needed. It
+;; is called when Gnus exits a group.
+;;
+;; `choke-request-article ARTICLE &optional GROUP SERVER'
+;; Return ARTICLE, which is either an article number or
+;; message-id. Note that not all backends can return articles based on
+;; message-id. 
+;;
+;; `choke-request-list SERVER'
+;; Return a list of all newsgroups on SERVER.
+;;
+;; `choke-request-list-newsgroups SERVER'
+;; Return a list of descriptions of all newsgroups on SERVER.
+;;
+;; `choke-request-newgroups DATE &optional SERVER'
+;; Return a list of all groups that have arrived after DATE on
+;; SERVER. Note that the date doesn't have to be respected - Gnus will
+;; always check whether the groups are old or not. Backends that do
+;; not store date information may just return the entire list of
+;; groups, although this might not be a good idea in general.
+;;
+;; `choke-request-post-buffer METHOD HEADER ARTICLE-BUFFER GROUP INFO'
+;; Should return a buffer that is suitable for "posting". nnspool and
+;; nntp return a `*post-buffer*', and nnmail return a `*mail*'
+;; buffer. This function should fill out the appropriate headers. 
+;;
+;; `choke-request-post &optional SERVER'
+;; Function that will be called from a buffer to be posted. 
+;;
+;; `choke-open-server SERVER &optional ARGUMENT'
+;; Open a connection to SERVER.
+;;
+;; `choke-close-server &optional SERVER'
+;; Close the connection to SERVER.
+;;
+;; `choke-server-opened &optional SERVER'
+;; Whether the conenction to SERVER is opened or not.
+;;
+;; `choke-server-status &optional SERVER'
+;; Should return a status string (not in the nntp buffer, but as the
+;; result of the function).
+;;
+;; The following functions are optional and apply only to backends
+;; that are able to control the contents of their groups totally
+;; (ie. mail backends.)  Backends that aren't able to do that
+;; shouldn't define these functions at all. Gnus will check for their
+;; presence before attempting to call them.
+;;
+;; `choke-request-expire-articles ARTICLES &optional NEWSGROUP SERVER'
+;; Should expire (according to some aging scheme) all ARTICLES. Most
+;; backends will not be able to expire articles. Should return a list
+;; of all articles that were not expired.
+;;
+;; `choke-request-move-article ARTICLE GROUP SERVER ACCEPT-FORM &optional LAST'
+;; Should move ARTICLE from GROUP on SERVER by using ACCEPT-FORM.
+;; Removes any information it has added to the article (extra headers,
+;; whatever - make it as clean as possible), and then passes the
+;; article on by evaling ACCEPT-FORM, which is normally a call to the
+;; function described below. If the ACCEPT-FORM returns a non-nil
+;; value, the article should then be deleted. If LAST is nil, that
+;; means that there will be further calls to this function. This might
+;; be taken as an advice not to save buffers/internal variables just
+;; yet, but wait until the last call to speed things up.
+;;
+;; `choke-request-accept-article GROUP &optional LAST' 
+;; The contents of the current buffer will be put into GROUP.  There
+;; should, of course, be an article in the current buffer.  This
+;; function is normally only called by the function described above,
+;; and LAST works the same way as in that function.
+;;
+;; `choke-request-replace-article ARTICLE GROUP BUFFER'
+;; Replace ARTICLE in GROUP with the contents of BUFFER.
+;; This provides an easy interface for allowing editing of
+;; articles. Note that even headers may be edited, so the backend has
+;; to update any tables (nov buffers, etc) that it maintains after
+;; replacing the article.
+;;
+;; All these functions must return nil if they couldn't service the
+;; request. If the optional arguments are not supplied, some "current"
+;; or "default" values should be used. In short, one should emulate an
+;; NNTP server, in a way.
+;;
+;; If you want to write a new backend, you just have to supply the
+;; functions listed above. In addition, you must enter the new backend
+;; into the list of valid select methods:
+;; (setq gnus-valid-select-methods 
+;;       (cons '("choke" mail) gnus-valid-select-methods))
+;; The first element in this list is the name of the backend. Other
+;; elemnets may be `mail' (for mail groups),  `post' (for news
+;; groups), `none' (neither), `respool' (for groups that can control
+;; their contents). 
+
 (defun gnus-start-news-server (&optional confirm)
   "Open a method for getting news.
 If CONFIRM is non-nil, the user will be asked for an NNTP server."
@@ -11460,13 +11816,22 @@ is returned insted of the status string."
   (funcall (gnus-get-function method 'server-opened) (nth 1 method)))
 
 (defun gnus-status-message (method)
-  (funcall (gnus-get-function method 'status-message) (nth 1 method)))
+  (let ((method (if (stringp method) (gnus-find-method-for-group method)
+                 method)))
+    (funcall (gnus-get-function method 'status-message) (nth 1 method))))
 
 (defun gnus-request-group (group &optional dont-check)
   (let ((method (gnus-find-method-for-group group)))
     (funcall (gnus-get-function method 'request-group) 
             (gnus-group-real-name group) (nth 1 method) dont-check)))
 
+(defun gnus-request-group-description (group)
+  (let ((method (gnus-find-method-for-group group))
+       (func 'request-group-description))
+    (and (gnus-check-backend-function func group)
+        (funcall (gnus-get-function method func) 
+                 (gnus-group-real-name group) (nth 1 method)))))
+
 (defun gnus-close-group (group)
   (let ((method (gnus-find-method-for-group group)))
     (funcall (gnus-get-function method 'close-group) 
@@ -11488,9 +11853,9 @@ is returned insted of the status string."
             article (gnus-group-real-name group) (nth 1 method))))
 
 ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>.
-(defun gnus-request-post-buffer (post header artbuf)
-   (let* ((group gnus-newsgroup-name)
-         (info (nth 2 (gnus-gethash group gnus-newsrc-hashtb)))
+(defun gnus-request-post-buffer (post group subject header artbuf
+                                     info follow-to respect-poster)
+   (let* ((info (or info (nth 2 (gnus-gethash group gnus-newsrc-hashtb))))
          (method
           (if (and gnus-post-method
                    ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>.
@@ -11500,8 +11865,11 @@ is returned insted of the status string."
                                        gnus-valid-select-methods)))
               gnus-post-method
             (gnus-find-method-for-group gnus-newsgroup-name))))
-    (funcall (gnus-get-function method 'request-post-buffer) 
-            post header artbuf (gnus-group-real-name group) info)))
+     (let ((mail-self-blind nil)
+          (mail-archive-file-name nil))
+       (funcall (gnus-get-function method 'request-post-buffer) 
+               post group subject header artbuf info follow-to
+               respect-poster))))
 
 (defun gnus-request-post (method &optional force)
   (and (not force) gnus-post-method
@@ -11517,18 +11885,19 @@ is returned insted of the status string."
             articles (gnus-group-real-name group) (nth 1 method)
             force)))
 
-(defun gnus-request-move-article (article group server accept-function)
+(defun gnus-request-move-article 
+  (article group server accept-function &optional last)
   (let ((method (gnus-find-method-for-group group)))
     (funcall (gnus-get-function method 'request-move-article) 
             article (gnus-group-real-name group) 
-            (nth 1 method) accept-function)))
+            (nth 1 method) accept-function last)))
 
-(defun gnus-request-accept-article (group)
+(defun gnus-request-accept-article (group &optional last)
   (let ((func (if (symbolp group) group
                (car (gnus-find-method-for-group group)))))
     (funcall (intern (format "%s-request-accept-article" func))
-            (if (stringp group) (gnus-group-real-name group)
-              group))))
+            (if (stringp group) (gnus-group-real-name group) group)
+            last)))
 
 (defun gnus-request-replace-article (article group buffer)
   (let ((func (car (gnus-find-method-for-group group))))
@@ -11536,11 +11905,14 @@ is returned insted of the status string."
             article (gnus-group-real-name group) buffer)))
 
 (defun gnus-find-method-for-group (group)
-  (let ((info (nth 2 (gnus-gethash group gnus-newsrc-hashtb))))
-    (if (or (not info)
-           (not (nth 4 info)))
-       gnus-select-method
-      (nth 4 info))))
+  (or gnus-override-method
+      (and (not group)
+          gnus-select-method)
+      (let ((info (nth 2 (gnus-gethash group gnus-newsrc-hashtb))))
+       (if (or (not info)
+               (not (nth 4 info)))
+           gnus-select-method
+         (nth 4 info)))))
 
 (defun gnus-check-backend-function (func group)
   (let ((method (if (stringp group) (car (gnus-find-method-for-group group))
@@ -11663,37 +12035,36 @@ The `-n' option line from .newsrc is respected."
                       groups (if (> groups 1) "s have" " has")))))))
 
 (defun gnus-ask-server-for-new-groups ()
-  (let* ((date (timezone-parse-date (or gnus-newsrc-last-checked-date
-                                       (current-time-string))))
+  (let* ((date (or gnus-newsrc-last-checked-date (current-time-string)))
         (methods (cons gnus-select-method 
                        (append
                         (and (consp gnus-check-new-newsgroups)
                              gnus-check-new-newsgroups)
                         gnus-secondary-select-methods)))
-        (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)))
         (groups 0)
         (new-date (current-time-string))
-        hashtb group new-newsgroups)
+        hashtb group new-newsgroups got-new)
     ;; Go thorugh both primary and secondary select methods and
     ;; request new newsgroups.  
     (while methods
-      (if (gnus-request-newgroups time-string (car methods))
+      (if (gnus-request-newgroups date (car methods))
          (save-excursion
+           (setq got-new t)
            (or hashtb (setq hashtb (gnus-make-hashtable 
                                     (count-lines (point-min) (point-max)))))
            (set-buffer nntp-server-buffer)
            ;; Enter all the new groups in a hashtable.
            (gnus-active-to-gnus-format (car methods) hashtb)))
       (setq methods (cdr methods)))
+    (and got-new (setq gnus-newsrc-last-checked-date new-date))
     ;; Now all new groups from all select methods are in `hashtb'.
     (mapatoms
      (lambda (group-sym)
        (setq group (symbol-name group-sym))
-       (if (gnus-gethash group gnus-active-hashtb)
+       (if (or (gnus-gethash group gnus-newsrc-hashtb)
+              (member group gnus-zombie-list)
+              (member group gnus-killed-list))
+          ;; The group is already known.
           ()
         (gnus-sethash group (symbol-value group-sym) gnus-active-hashtb)
         (if (and gnus-newsrc-options-n-yes
@@ -11712,14 +12083,15 @@ The `-n' option line from .newsrc is respected."
      hashtb)
     (if new-newsgroups 
        (gnus-subscribe-hierarchical-interactive new-newsgroups))
-    (setq gnus-newsrc-last-checked-date new-date)
     ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
     (if (> groups 0)
        (message "%d new newsgroup%s arrived." 
-                groups (if (> groups 1) "s have" " has")))))
+                groups (if (> groups 1) "s have" " has")))
+    got-new))
 
 (defun gnus-check-first-time-used ()
-  (if (or (file-exists-p gnus-startup-file)
+  (if (or (> (length gnus-newsrc-assoc) 1)
+         (file-exists-p gnus-startup-file)
          (file-exists-p (concat gnus-startup-file ".el"))
          (file-exists-p (concat gnus-startup-file ".eld")))
       nil
@@ -11745,9 +12117,9 @@ The `-n' option line from .newsrc is respected."
          (if (gnus-gethash (car groups) gnus-active-hashtb)
              (gnus-group-change-level (car groups) 3 9))
          (setq groups (cdr groups)))
-       (gnus-group-make-doc-group)
-       (message
-        (substitute-command-keys "\\<gnus-group-mode-map>\\[gnus-group-list-killed] to list killed groups"))))))
+       (gnus-group-make-help-group)
+       (and gnus-novice-user
+            (message (substitute-command-keys "\\<gnus-group-mode-map>\\[gnus-group-list-killed] to list killed groups")))))))
 
 ;; `gnus-group-change-level' is the fundamental function for changing
 ;; subscription levels of newsgroups. This might mean just changing
@@ -11767,7 +12139,8 @@ The `-n' option line from .newsrc is respected."
 ;; after. 
 (defun gnus-group-change-level (entry level &optional oldlevel
                                      previous fromkilled)
-  (let (group info active num)
+  (let ((pinfo entry)
+       group info active num)
     ;; Glean what info we can from the arguments
     (if (consp entry)
        (if fromkilled (setq group (nth 1 entry))
@@ -11823,17 +12196,16 @@ The `-n' option line from .newsrc is respected."
                     (progn
                       (setq info (cdr entry))
                       (setq num (car entry)))
-                  (setq active (gnus-gethash group gnus-active-hashtb))
+                  (setq active (or (gnus-gethash group gnus-active-hashtb)
+                                   '(0 . 0)))
                   (setq num (- (1+ (cdr active)) (car active)))
                   ;; Check whether the group is foreign. If so, the
                   ;; foreign select method has to be entered into the
                   ;; info. 
                   (let ((method (gnus-group-method-name group)))
                     (if (eq method gnus-select-method)
-                        (setq info (list group level 
-                                         (cons 1 (1- (car active)))))
-                      (setq info (list group level (cons 1 (1- (car active)))
-                                       nil method)))))
+                        (setq info (list group level nil))
+                      (setq info (list group level nil nil method)))))
                 (setq entry (cons info (if previous (cdr (cdr previous))
                                          (cdr gnus-newsrc-assoc))))
                 (setcdr (if previous (cdr previous) gnus-newsrc-assoc)
@@ -11896,22 +12268,23 @@ newsgroup."
                   (delete group (symbol-value (car dead-lists)))))
          (setq killed (cdr killed)))
        (setq dead-lists (cdr dead-lists))))
-    ;; While we're at it, we check the killed list for duplicates.
-    ;; This has nothing to do with bogosity, but it's a convenient
-    ;; place to put the check.
-    (let ((killed gnus-killed-list))
-      (while killed
-       (message "%d" (length killed))
-       (setcdr killed (delete (car killed) (cdr killed)))
-       (setq killed (cdr killed))))
     (message "Checking bogus newsgroups... done")))
 
+(defun gnus-check-duplicate-killed-groups ()
+  "Remove duplicates from the list of killed groups."
+  (interactive)
+  (let ((killed gnus-killed-list))
+    (while killed
+      (message "%d" (length killed))
+      (setcdr killed (delete (car killed) (cdr killed)))
+      (setq killed (cdr killed)))))
+
 ;; Go though `gnus-newsrc-assoc' and compare with `gnus-active-hashtb'
 ;; and compute how many unread articles there are in each group.
 (defun gnus-get-unread-articles (&optional level)
   (let ((newsrc (cdr gnus-newsrc-assoc))
        (level (or level 6))
-       info group active)
+       info group active virtuals)
     (message "Checking new news...")
     (while newsrc
       (setq info (car newsrc))
@@ -11929,8 +12302,9 @@ newsgroup."
                  (and (numberp gnus-activate-foreign-newsgroups)
                       (<= (nth 1 info) gnus-activate-foreign-newsgroups)
                       (<= (nth 1 info) level)))
-             (or (eq (car (nth 4 info)) 'nnvirtual)
-                 (setq active (gnus-activate-newsgroup (car info)))))
+             (if (eq (car (nth 4 info)) 'nnvirtual)
+                 (setq virtuals (cons info virtuals))
+               (setq active (gnus-activate-newsgroup (car info)))))
        (if (and (not gnus-read-active-file)
                 (<= (nth 1 info) level))
            (progn
@@ -11940,6 +12314,15 @@ newsgroup."
                        (setcar (gnus-gethash group gnus-newsrc-hashtb) t)))
       (and active (gnus-get-unread-articles-in-group info active))
       (setq newsrc (cdr newsrc)))
+
+    ;; Activate the virtual groups. This has to be done after all the
+    ;; other groups. 
+    ;; !!! If one virtual group contains another virtual group, even
+    ;; doing it this way might cause problems.
+    (while virtuals
+      (gnus-activate-newsgroup (car (car virtuals)))
+      (setq virtuals (cdr virtuals)))
+
     (message "Checking new news... done")))
 
 ;; Create a hash table out of the newsrc alist. The `car's of the
@@ -11950,7 +12333,7 @@ newsgroup."
     (setq gnus-newsrc-hashtb (gnus-make-hashtable (length alist)))
     (setq alist 
          (setq prev (setq gnus-newsrc-assoc 
-                          (cons (list "dummy.group" 0 (cons 0 0)) alist))))
+                          (cons (list "dummy.group" 0 nil) alist))))
     (while alist
       (gnus-sethash (car (car alist)) (cons nil prev) gnus-newsrc-hashtb)
       (setq prev alist)
@@ -11974,7 +12357,7 @@ newsgroup."
   (let* ((range (nth 2 info))
         (num 0)
         (marked (nth 3 info))
-        srange lowest group)
+        srange lowest group highest)
     ;; 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.
@@ -11985,22 +12368,30 @@ newsgroup."
          ((atom (car range))
           ;; Fix a single (num . num) range according to the
           ;; active hash table.
-          (if (< (cdr range) (car active)) (setcdr range (car active)))
+          (and (< (cdr range) (car active)) (setcdr range (car active)))
+          (and (> (cdr range) (cdr active)) (setcdr range (cdr active)))
           ;; Compute number of unread articles.
           (setq num (max 0 (- (cdr active) 
                               (- (1+ (cdr range)) (car range))))))
          (t
           ;; The read list is a list of ranges. Fix them according to
           ;; the active hash table.
-          (setq srange range)
-          (setq lowest (1- (car active)))
-          (while (and (< (cdr (car srange)) lowest))
-            (if (and (cdr srange)
-                     (<= (cdr (car srange)) (1+ lowest)))
+          (while (and (cdr range) (>= (car active) (car (car (cdr range)))))
+            (setcdr (car range) (cdr (car (cdr range))))
+            (setcdr range (cdr (cdr range))))
+          (if (< (cdr (car range)) (car active)) 
+              (setcdr (car range) (car active)))
+          (let ((srange range))
+            (while (and (cdr srange) 
+                        (<= (car (car (cdr srange))) (cdr active)))
+              (setq srange (cdr srange)))
+            (if (cdr srange)
                 (progn
-                  (setcdr (car srange) (cdr (car (cdr srange))))
-                  (setcdr srange (cdr (cdr srange))))
-              (setcdr (car srange) lowest)))
+                  (setcdr srange nil)
+                  (if (> (cdr (car srange)) (cdr active))
+                      (setcdr (car srange) (cdr active)))))
+            (if (and srange (> (cdr (car srange)) (cdr active)))
+                (setcdr (car srange) (cdr active))))
           ;; Compute the number of unread articles.
           (while range
             (setq num (+ num (- (1+ (cdr (car range))) 
@@ -12008,16 +12399,34 @@ newsgroup."
             (setq range (cdr range)))
           (setq num (max 0 (- (cdr active) num)))))
     (and info
-        (setcar (gnus-gethash (car info) gnus-newsrc-hashtb) 
-                (max 0 (- num (length (cdr (assq 'tick marked)))
-                          (length (cdr (assq 'dormant marked)))))))
+        (progn
+          (and (assq 'tick marked)
+               (inline (gnus-remove-illegal-marked-articles
+                        (assq 'tick marked) (nth 2 info))))
+          (and (assq 'dormant marked)
+               (inline (gnus-remove-illegal-marked-articles
+                        (assq 'dormant marked) (nth 2 info))))
+          (setcar
+           (gnus-gethash (car info) gnus-newsrc-hashtb) 
+           (setq num (max 0 (- num (length (cdr (assq 'tick marked)))
+                               (length (cdr (assq 'dormant marked)))))))))
     num))
 
+(defun gnus-remove-illegal-marked-articles (marked ranges)
+  (let ((m (cdr marked)))
+    ;; Make sure that all ticked articles are a subset of the unread
+    ;; articles. 
+    (while m
+      (if (gnus-member-of-range (car m) ranges)
+         (setcdr marked (cdr m))
+       (setq marked m))
+      (setq m (cdr m)))))
+
 (defun gnus-activate-newsgroup (group)
   (let ((method (gnus-find-method-for-group group))
        active)
-    (or (gnus-server-opened method) (gnus-open-server method))
-    (and (gnus-request-group group)
+    (and (or (gnus-server-opened method) (gnus-open-server method))
+        (gnus-request-group group)
         (save-excursion
           (set-buffer nntp-server-buffer)
           (goto-char 1)
@@ -12027,8 +12436,8 @@ newsgroup."
                  (gnus-sethash 
                   group (setq active (cons (read (current-buffer))
                                            (read (current-buffer))))
-                  gnus-active-hashtb)))))
-    active))
+                  gnus-active-hashtb))
+               active)))))
 
 (defun gnus-update-read-articles 
   (group unread unselected ticked &optional domarks replied expirable killed
@@ -12055,8 +12464,7 @@ Returns whether the updating was successful."
       ;; Remove any negative articles numbers.
       (while (and unread (< (car unread) 0))
        (setq unread (cdr unread)))
-      (if (not (and (numberp number) (zerop number)))
-         (setq unread (nconc unselected unread)))
+      (setq unread (sort (append unselected unread) '<))
       ;; Set the number of unread articles in gnus-newsrc-hashtb.
       (setcar entry (max 0 (- (length unread) (length ticked) 
                              (length dormant))))
@@ -12085,7 +12493,9 @@ Returns whether the updating was successful."
 
 (defun gnus-make-articles-unread (group articles)
   "Mark ARTICLES in GROUP as unread."
-  (let ((info (nth 2 (gnus-gethash group gnus-newsrc-hashtb))))
+  (let ((info (nth 2 (or (gnus-gethash group gnus-newsrc-hashtb)
+                        (gnus-gethash (gnus-group-real-name group)
+                                      gnus-newsrc-hashtb)))))
     (setcar (nthcdr 2 info)
            (gnus-remove-from-range (nth 2 info) articles))
     (gnus-group-update-group group t)))
@@ -12276,8 +12686,7 @@ If FORCE is non-nil, the .newsrc file is read."
   (let* ((file (expand-file-name file nil))
         (real-file (concat file "-" (nth 1 gnus-select-method))))
     (if (file-exists-p real-file)
-       real-file file)
-    ))
+       real-file file)))
 
 ;; jwz: rewrote this function to be much more efficient, and not be subject
 ;; to regexp overflow errors when it encounters very long lines -- the old
@@ -12487,8 +12896,7 @@ If FORCE is non-nil, the .newsrc file is read."
             (setq no (cons newsgroup no)))
            ((string-equal newsgroup ".+")) ;Ignore `all'.
            (t
-            (setq yes (cons newsgroup yes))))
-      )
+            (setq yes (cons newsgroup yes)))))
     ;; Make a cons of regexps from parsing result.
     ;; We have to append \(\.\|$\) to prevent matching substring of
     ;; newsgroup.  For example, "jp.net" should not match with
@@ -12509,8 +12917,7 @@ If FORCE is non-nil, the .newsrc file is read."
                              (lambda (newsgroup)
                                (concat newsgroup "\\|"))
                              (cdr no)))
-                     (car no) "\\)\\(\\.\\|$\\)")))
-    ))
+                     (car no) "\\)\\(\\.\\|$\\)")))))
 
 (defun gnus-save-newsrc-file ()
   "Save .newsrc file."
@@ -12519,9 +12926,11 @@ If FORCE is non-nil, the .newsrc file is read."
   (and (or gnus-newsrc-assoc gnus-killed-list)
        gnus-current-startup-file
        (save-excursion
-        (if (zerop (save-excursion
-                   (set-buffer gnus-dribble-buffer)
-                   (buffer-size)))
+        (if (or (not gnus-dribble-buffer)
+                (not (buffer-name gnus-dribble-buffer))
+                (zerop (save-excursion
+                         (set-buffer gnus-dribble-buffer)
+                         (buffer-size))))
             (message "(No changes need to be saved)")
           (if gnus-save-newsrc-file
               (let ((make-backup-files t)
@@ -12620,7 +13029,7 @@ If FORCE is non-nil, the .newsrc file is read."
        (save-restriction
          (set-buffer nntp-server-buffer)
          (goto-char (point-min))
-         (delete-non-matching-lines "^[a-zA-Z\\.0-9]+[ \t]")
+         (delete-non-matching-lines "^[-\\._+A-Za-z0-9]+[ \t]")
          (goto-char (point-min))
          (if (or (search-forward "\n.\n" nil t)
                  (goto-char (point-max)))
@@ -12638,6 +13047,15 @@ If FORCE is non-nil, the .newsrc file is read."
       (message "Reading descriptions file...done")
       t)))
 
+(defun gnus-group-get-description (group)
+  ;; Get the description of a group by sending XGTITLE to the server.
+  (and (gnus-request-group-description group)
+       (save-excursion
+        (set-buffer nntp-server-buffer)
+        (goto-char (point-min))
+        (and (looking-at "[^ \t]+[ \t]+\\(.*\\)")
+             (buffer-substring (match-beginning 1) (match-end 1))))))
+
 (provide 'gnus)
 
 ;;; gnus.el ends here
index 746f9db..2dd41ac 100644 (file)
@@ -1,7 +1,7 @@
 ;;; nnbabyl.el --- mail mbox access for Gnus
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
@@ -126,7 +126,7 @@ If the stream is opened, return T, otherwise return NIL."
   (and nntp-server-buffer
        (get-buffer nntp-server-buffer)))
 
-(defun nnbabyl-status-message ()
+(defun nnbabyl-status-message (&optional server)
   "Return server status response as string."
   nnbabyl-status-string)
 
@@ -234,7 +234,8 @@ the date."
       (save-buffer)
       rest)))
 
-(defun nnbabyl-request-move-article (article group server accept-form)
+(defun nnbabyl-request-move-article 
+  (article group server accept-form &optional last)
   (nnbabyl-possibly-change-newsgroup group)
   (let ((buf (get-buffer-create " *nnbabyl move*"))
        result)
@@ -257,10 +258,10 @@ the date."
        (goto-char 1)
        (if (search-forward (nnbabyl-article-string article) nil t)
           (nnbabyl-delete-mail))
-       (save-buffer)))
+       (and last (save-buffer))))
     result))
 
-(defun nnbabyl-request-accept-article (group)
+(defun nnbabyl-request-accept-article (group &optional last)
   (let ((buf (current-buffer))
        result beg)
     (and 
@@ -279,7 +280,7 @@ the date."
                 (delete-region (point) (progn (forward-line 1) (point)))))
             (setq result (nnbabyl-insert-newsgroup-line group)))
         (setq result (nnbabyl-save-mail)))
-       (save-buffer)
+       (and last (save-buffer))
        result)
      (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file))
     result))
@@ -330,19 +331,17 @@ delimeter line."
          (delete-region (point-min) (point-max))))))
 
 (defun nnbabyl-possibly-change-newsgroup (newsgroup)
-  (if (not (get-buffer nnbabyl-mbox-buffer))
+  (if (or (not nnbabyl-mbox-buffer)
+         (not (buffer-name nnbabyl-mbox-buffer)))
       (save-excursion
-       (let ((buf (or (get-buffer (file-name-nondirectory nnbabyl-mbox-file))
-                      (create-file-buffer nnbabyl-mbox-file))))
-         (set-buffer (setq nnbabyl-mbox-buffer buf))
-         (insert-file-contents nnbabyl-mbox-file)
-         (setq buffer-file-name nnbabyl-mbox-file))
-       (buffer-disable-undo (current-buffer))))
+       (nnbabyl-read-mbox)))
   (if (not nnbabyl-group-alist)
       (setq nnbabyl-group-alist (nnmail-get-active)))
   (if newsgroup
       (if (assoc newsgroup nnbabyl-group-alist)
-         (setq nnbabyl-current-group newsgroup))))
+         (setq nnbabyl-current-group newsgroup)
+       (setq nnbabyl-status-string "No such group in file")
+       nil)))
 
 (defun nnbabyl-article-string (article)
   (concat "\nX-Gnus-Newsgroup: " nnbabyl-current-group ":" 
@@ -396,34 +395,37 @@ delimeter line."
                     (create-file-buffer nnbabyl-mbox-file)))
            start end)
        (set-buffer (setq nnbabyl-mbox-buffer buf))
+       (buffer-disable-undo (current-buffer))
+
        (insert-file-contents nnbabyl-mbox-file)
        (setq buffer-file-name nnbabyl-mbox-file)
+       (set-buffer-modified-p nil)
 
-       (buffer-disable-undo (current-buffer))
        (goto-char (point-min))
        (while (re-search-forward delim nil t)
          (setq start (match-beginning 0))
-         (if (not (search-forward "\nX-Gnus-Newsgroup: " 
-                                  (save-excursion 
-                                    (setq end
-                                          (or
-                                           (and
-                                            (re-search-forward delim nil t)
-                                            (match-beginning 0))
-                                           (point-max))))
-                                  t))
-             (goto-char end)
-             (save-excursion
-               (save-restriction
-                 (goto-char start)
-                 (narrow-to-region start end)
-                 (nnbabyl-save-mail))))
-         )))))
+         (if (and
+              (save-excursion (re-search-forward delim nil t))
+              (not (search-forward 
+                    "\nX-Gnus-Newsgroup: " 
+                    (save-excursion 
+                      (setq end (or (and (re-search-forward delim nil t)
+                                         (match-beginning 0))
+                                    (point-max)))) t)))
+             (progn
+               (goto-char end)
+               (save-excursion
+                 (save-restriction
+                   (goto-char start)
+                   (narrow-to-region start end)
+                   (nnbabyl-save-mail))))))
+       (save-buffer)
+       (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)))))
 
 (defun nnbabyl-get-new-mail ()
   (let (incoming)
     (nnbabyl-read-mbox)
-    (if (and nnmail-spool-file
+    (if (and nnmail-spool-file nnbabyl-get-new-mail
             (file-exists-p nnmail-spool-file)
             (> (nth 7 (file-attributes nnmail-spool-file)) 0))
        (progn
index e24cf78..5fcae1c 100644 (file)
@@ -1,7 +1,7 @@
 ;;; nndigest.el --- digest access for Gnus
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
index 6545128..ba6b85a 100644 (file)
@@ -1,9 +1,9 @@
 ;;; nndir.el --- single directory newsgroup access for Gnus
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
+;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
index b65cc5e..b7700bd 100644 (file)
@@ -1,9 +1,9 @@
 ;;; nndoc.el --- single file access for Gnus
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;; Keywords: news, mail
+;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
@@ -96,7 +96,7 @@ Newsgroup must be selected before calling this function."
   (and nntp-server-buffer
        (get-buffer nntp-server-buffer)))
 
-(defun nndoc-status-message ()
+(defun nndoc-status-message (&optional server)
   "Return server status response as string."
   nndoc-status-string)
 
@@ -126,20 +126,23 @@ Newsgroup must be selected before calling this function."
 (defun nndoc-request-group (group &optional server dont-check)
   "Select news GROUP."
   (save-excursion
-    (nndoc-possibly-change-buffer group server)
-    (if dont-check
-       t
-      (save-excursion
-       (set-buffer nntp-server-buffer)
-       (erase-buffer)
-       (let ((number (nndoc-number-of-articles)))
-         (if (zerop number)
-             (progn
-               (nndoc-close-group group)
-               nil)
-           (insert (format "211 %d %d %d %s\n" 
-                           number 1 number group))
-           t))))))
+    (if (not (nndoc-possibly-change-buffer group server))
+       (progn
+         (setq nndoc-status-string "No such file")
+         nil)
+      (if dont-check
+         t
+       (save-excursion
+         (set-buffer nntp-server-buffer)
+         (erase-buffer)
+         (let ((number (nndoc-number-of-articles)))
+           (if (zerop number)
+               (progn
+                 (nndoc-close-group group)
+                 nil)
+             (insert (format "211 %d %d %d %s\n" 
+                             number 1 number group))
+             t)))))))
 
 (defun nndoc-close-group (group &optional server)
   (nndoc-possibly-change-buffer group server)
@@ -173,16 +176,20 @@ Newsgroup must be selected before calling this function."
                 (setq buf (cdr (assoc group nndoc-group-alist)))))
        (if buf 
            (setq nndoc-current-buffer buf)
-         (setq nndoc-group-alist 
-               (cons (cons group (setq nndoc-current-buffer 
-                                       (get-buffer-create 
-                                        (concat " *nndoc " group "*"))))
-                     nndoc-group-alist))
-         (save-excursion
-           (set-buffer nndoc-current-buffer)
-           (buffer-disable-undo (current-buffer))
-           (erase-buffer)
-           (insert-file-contents file))))))
+         (if (or (not (file-exists-p file))
+                 (file-directory-p file))
+             ()
+           (setq nndoc-group-alist 
+                 (cons (cons group (setq nndoc-current-buffer 
+                                         (get-buffer-create 
+                                          (concat " *nndoc " group "*"))))
+                       nndoc-group-alist))
+           (save-excursion
+             (set-buffer nndoc-current-buffer)
+             (buffer-disable-undo (current-buffer))
+             (erase-buffer)
+             (insert-file-contents file)
+             t))))))
 
 (defun nndoc-number-of-articles ()
   (save-excursion
diff --git a/lisp/nnfolder.el b/lisp/nnfolder.el
new file mode 100644 (file)
index 0000000..998db04
--- /dev/null
@@ -0,0 +1,458 @@
+;;; nnfolder.el --- mail folder access for Gnus
+;; Copyright (C) 1995 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'nnheader)
+(require 'rmail)
+(require 'nnmail)
+
+(defvar nnfolder-directory (expand-file-name "~/Mail/")
+  "The name of the mail box file in the users home directory.")
+
+(defvar nnfolder-active-file (concat nnfolder-directory  "active")
+  "The name of the active file.")
+
+(defvar nnfolder-newsgroups-file (concat nnfolder-directory "newsgroups")
+  "Mail newsgroups description file.")
+
+(defvar nnfolder-get-new-mail t
+  "If non-nil, nnml will check the incoming mail file and split the mail.")
+
+\f
+
+(defconst nnfolder-version "nnfolder 0.1"
+  "nnfolder version.")
+
+(defvar nnfolder-current-group nil)
+(defvar nnfolder-current-buffer nil)
+(defvar nnfolder-status-string "")
+(defvar nnfolder-group-alist nil)
+(defvar nnfolder-buffer-alist nil)
+
+;;; Interface functions
+
+(defun nnfolder-retrieve-headers (sequence &optional newsgroup server)
+  "Retrieve the headers for the articles in SEQUENCE.
+Newsgroup must be selected before calling this function."
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer)
+    (let ((file nil)
+         (number (length sequence))
+         beg article art-string start stop)
+      (nnfolder-possibly-change-group newsgroup)
+      (while sequence
+       (setq article (car sequence))
+       (setq art-string (nnfolder-article-string article))
+       (set-buffer nnfolder-current-buffer)
+       (if (or (search-forward art-string nil t)
+               (progn (goto-char 1)
+                      (search-forward art-string nil t)))
+           (progn
+             (setq start 
+                   (save-excursion
+                     (re-search-backward 
+                      (concat "^" rmail-unix-mail-delimiter) nil t)
+                     (point)))
+             (search-forward "\n\n" nil t)
+             (setq stop (1- (point)))
+             (set-buffer nntp-server-buffer)
+             (insert (format "221 %d Article retrieved.\n" article))
+             (setq beg (point))
+             (insert-buffer-substring nnfolder-current-buffer start stop)
+             (goto-char (point-max))
+             (insert ".\n")))
+       (setq sequence (cdr sequence)))
+
+      ;; Fold continuation lines.
+      (goto-char 1)
+      (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
+       (replace-match " " t t))
+      'headers)))
+
+(defun nnfolder-open-server (host &optional service)
+  "Open mbox backend."
+  (setq nnfolder-status-string "")
+  (setq nnfolder-group-alist nil)
+  (nnheader-init-server-buffer))
+
+(defun nnfolder-close-server (&optional server)
+  "Close news server."
+  t)
+
+(defun nnfolder-server-opened (&optional server)
+  "Return server process status, T or NIL.
+If the stream is opened, return T, otherwise return NIL."
+  (and nntp-server-buffer
+       (buffer-name nntp-server-buffer)))
+
+(defun nnfolder-status-message (&optional server)
+  "Return server status response as string."
+  nnfolder-status-string)
+
+(defun nnfolder-request-article (article &optional newsgroup server buffer)
+  "Select ARTICLE by number."
+  (nnfolder-possibly-change-group newsgroup)
+  (if (stringp article)
+      nil
+    (save-excursion
+      (set-buffer nnfolder-current-buffer)
+      (goto-char 1)
+      (if (search-forward (nnfolder-article-string article) nil t)
+         (let (start stop)
+           (re-search-backward (concat "^" rmail-unix-mail-delimiter) nil t)
+           (setq start (point))
+           (forward-line 1)
+           (or (and (re-search-forward 
+                     (concat "^" rmail-unix-mail-delimiter) nil t)
+                    (forward-line -1))
+               (goto-char (point-max)))
+           (setq stop (point))
+           (let ((nntp-server-buffer (or buffer nntp-server-buffer)))
+             (set-buffer nntp-server-buffer)
+             (erase-buffer)
+             (insert-buffer-substring nnfolder-current-buffer start stop)
+             (goto-char (point-min))
+             (while (looking-at "From ")
+               (delete-char 5)
+               (insert "X-From-Line: ")
+               (forward-line 1))
+             t))))))
+
+(defun nnfolder-request-group (group &optional server dont-check)
+  "Select news GROUP."
+  (save-excursion
+    (nnfolder-possibly-change-group group)
+    (and (assoc group nnfolder-group-alist)
+        (save-excursion
+          (set-buffer nntp-server-buffer)
+          (erase-buffer)
+          (if dont-check
+              t
+            (nnfolder-get-new-mail)
+            (let ((active (assoc group nnfolder-group-alist)))
+              (insert (format "211 %d %d %d %s\n" 
+                              (1+ (- (cdr (car (cdr active)))
+                                     (car (car (cdr active)))))
+                              (car (car (cdr active)))
+                              (cdr (car (cdr active)))
+                              (car active))))
+            t)))))
+
+(defun nnfolder-close-group (group &optional server)
+  t)
+
+(defun nnfolder-request-list (&optional server)
+  "List active newsgoups."
+  (if server (nnfolder-get-new-mail))
+  (or (nnmail-find-file nnfolder-active-file)
+      (progn
+       (setq nnfolder-group-alist (nnmail-get-active))
+       (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
+       (nnmail-find-file nnfolder-active-file))))
+
+(defun nnfolder-request-newgroups (date &optional server)
+  "List groups created after DATE."
+  (nnfolder-request-list server))
+
+(defun nnfolder-request-list-newsgroups (&optional server)
+  "List newsgroups (defined in NNTP2)."
+  (nnmail-find-file nnfolder-newsgroups-file))
+
+(defun nnfolder-request-post (&optional server)
+  "Post a new news in current buffer."
+  (mail-send-and-exit nil))
+
+(fset 'nnfolder-request-post-buffer 'nnmail-request-post-buffer)
+
+(defun nnfolder-request-expire-articles (articles newsgroup &optional server force)
+  "Expire all articles in the ARTICLES list in group GROUP.
+The list of unexpired articles will be returned (ie. all articles that
+were too fresh to be expired).
+If FORCE is non-nil, the ARTICLES will be deleted without looking at
+the date."
+  (nnfolder-possibly-change-group newsgroup)
+  (let* ((days (or (and nnmail-expiry-wait-function
+                       (funcall nnmail-expiry-wait-function newsgroup))
+                  nnmail-expiry-wait))
+        article rest)
+    (save-excursion 
+      (set-buffer nnfolder-current-buffer)
+      (while articles
+       (goto-char 1)
+       (if (search-forward (nnfolder-article-string (car articles)) nil t)
+           (if (or force
+                   (> (nnmail-days-between 
+                       (current-time-string)
+                       (buffer-substring 
+                        (point) (progn (end-of-line) (point))))
+                      days))
+               (progn
+                 (and gnus-verbose-backends
+                      (message "Deleting: %s" (car articles)))
+                 (nnfolder-delete-mail))
+             (setq rest (cons (car articles) rest))))
+       (setq articles (cdr articles)))
+      (save-buffer)
+      rest)))
+
+(defun nnfolder-request-move-article
+  (article group server accept-form &optional last)
+  (nnfolder-possibly-change-group group)
+  (let ((buf (get-buffer-create " *nnfolder move*"))
+       result)
+    (and 
+     (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 
+              "^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))))
+       (setq result (eval accept-form))
+       (kill-buffer buf)
+       result)
+     (save-excursion
+       (nnfolder-possibly-change-group group)
+       (set-buffer nnfolder-current-buffer)
+       (goto-char 1)
+       (if (search-forward (nnfolder-article-string article) nil t)
+          (nnfolder-delete-mail))
+       (and last (save-buffer))))
+    result))
+
+(defun nnfolder-request-accept-article (group &optional last)
+  (nnfolder-possibly-change-group group)
+  (let ((buf (current-buffer))
+       result beg)
+    (debug (current-buffer))
+    (goto-char (point-min))
+    (if (looking-at "X-From-Line: ")
+       (replace-match "From ")
+      (insert "From nobody " (current-time-string) "\n"))
+    (and 
+     (nnfolder-request-list)
+     (setq nnfolder-group-alist (nnmail-get-active))
+     (progn
+       (set-buffer buf)
+       (goto-char (point-min))
+       (search-forward "\n\n" nil t)
+       (forward-line -1)
+       (while (re-search-backward "^X-Gnus-Newsgroup: " nil t)
+        (delete-region (point) (progn (forward-line 1) (point))))
+       (setq result (nnfolder-save-mail (and (stringp group) group))))
+     (save-excursion
+       (set-buffer nnfolder-current-buffer)
+       (insert-buffer-substring buf)
+       (and last (save-buffer))
+       result)
+     (nnmail-save-active nnfolder-group-alist nnfolder-active-file))
+    (car result)))
+
+(defun nnfolder-request-replace-article (article group buffer)
+  (nnfolder-possibly-change-group group)
+  (save-excursion
+    (set-buffer nnfolder-current-buffer)
+    (goto-char 1)
+    (if (not (search-forward (nnfolder-article-string article) nil t))
+       nil
+      (nnfolder-delete-mail t t)
+      (insert-buffer-substring buffer)
+      (save-buffer)
+      t)))
+
+\f
+;;; Internal functions.
+
+(defun nnfolder-delete-mail (&optional force leave-delim)
+  "If FORCE, delete article no matter how many X-Gnus-Newsgroup
+headers there are. If LEAVE-DELIM, don't delete the Unix mbox
+delimeter line."
+  ;; Beginning of the article.
+  (save-excursion
+    (save-restriction
+      (narrow-to-region
+       (save-excursion
+        (re-search-backward (concat "^" rmail-unix-mail-delimiter) nil t)
+        (if leave-delim (progn (forward-line 1) (point))
+          (match-beginning 0)))
+       (progn
+        (forward-line 1)
+        (or (and (re-search-forward (concat "^" rmail-unix-mail-delimiter) 
+                                    nil t)
+                 (if (and (not (bobp)) leave-delim)
+                     (progn (forward-line -2) (point))
+                   (match-beginning 0)))
+            (point-max))))
+      (delete-region (point-min) (point-max)))))
+
+(defun nnfolder-possibly-change-group (group)
+  (or (file-exists-p nnfolder-directory)
+      (make-directory (directory-file-name nnfolder-directory)))
+  (if (not nnfolder-group-alist)
+      (progn
+       (nnfolder-request-list)
+       (setq nnfolder-group-alist (nnmail-get-active))))
+  (or (assoc group nnfolder-group-alist)
+      (not (file-exists-p (concat nnfolder-directory group)))
+      (progn
+       (setq nnfolder-group-alist 
+             (cons (list group (cons 1 0)) nnfolder-group-alist))
+       (nnmail-save-active nnfolder-group-alist nnfolder-active-file)))
+  (let (inf file)
+    (if (and (equal group nnfolder-current-group)
+            (buffer-name nnfolder-current-buffer))
+       ()
+      (if (setq inf (member group nnfolder-buffer-alist))
+         (setq nnfolder-current-buffer (nth 1 inf)))
+      (setq nnfolder-current-group group)
+      (if (not (buffer-name nnfolder-current-buffer))
+         (progn
+           (setq nnfolder-buffer-alist (delq inf nnfolder-buffer-alist))
+           (setq inf nil)))
+      (if inf
+         ()
+       (save-excursion
+         (setq file (concat nnfolder-directory group))
+         (if (not (file-exists-p file))
+             (write-region 1 1 file t 'nomesg))
+         (set-buffer (nnfolder-read-folder file))
+         (setq nnfolder-buffer-alist (cons (list group (current-buffer))
+                                           nnfolder-buffer-alist))))))
+  (setq nnfolder-current-group group))
+
+(defun nnfolder-article-string (article)
+  (concat "\nX-Gnus-Article-Number: " (int-to-string article) " "))
+
+(defun nnfolder-save-mail (&optional group)
+  "Called narrowed to an article."
+  (let* ((nnmail-split-methods 
+         (if group (list (list group "")) nnmail-split-methods))
+        (group-art-list
+         (nreverse (nnmail-article-group 'nnfolder-active-number)))
+        group-art)
+    (nnmail-insert-lines)
+    (nnmail-insert-xref group-art-list)
+    (while group-art-list
+      (setq group-art (car group-art-list)
+           group-art-list (cdr group-art-list))
+      (nnfolder-possibly-change-group (car group-art))
+      (nnfolder-insert-newsgroup-line group-art)
+      (let ((beg (point-min))
+           (end (point-max))
+           (obuf (current-buffer)))
+       (save-excursion
+         (set-buffer nnfolder-current-buffer)
+         (goto-char (point-max))
+         (insert-buffer-substring obuf beg end)))
+      (goto-char (point-min))
+      (search-forward "\nX-Gnus-Article-Number: ")
+      (delete-region (progn (beginning-of-line) (point))
+                    (progn (forward-line 1) (point))))))
+
+(defun nnfolder-insert-newsgroup-line (group-art)
+  (save-excursion
+    (goto-char (point-min))
+    (if (search-forward "\n\n" nil t)
+       (progn
+         (forward-char -1)
+         (insert (format "X-Gnus-Article-Number: %d   %s\n" 
+                         (cdr group-art) (current-time-string)))))))
+
+(defun nnfolder-active-number (group)
+  "Find the next article number in GROUP."
+  (let ((active (car (cdr (assoc group nnfolder-group-alist)))))
+    (setcdr active (1+ (cdr active)))
+    (cdr active)))
+
+(defun nnfolder-read-folder (file)
+  (nnfolder-request-list)
+  (setq nnfolder-group-alist (nnmail-get-active))
+  (save-excursion
+    (set-buffer
+     (setq nnfolder-current-buffer 
+          (find-file-noselect file)))
+    (buffer-disable-undo (current-buffer))
+    (let ((delim (concat "^" rmail-unix-mail-delimiter))
+         start end)
+      (goto-char (point-min))
+      (while (re-search-forward delim nil t)
+       (setq start (match-beginning 0))
+       (if (not (search-forward "\nX-Gnus-Article-Number: " 
+                                (save-excursion 
+                                  (setq end
+                                        (or
+                                         (and
+                                          (re-search-forward delim nil t)
+                                          (match-beginning 0))
+                                         (point-max))))
+                                t))
+           (save-excursion
+             (save-restriction
+               (narrow-to-region start end)
+               (nnfolder-insert-newsgroup-line 
+                (cons nil (nnfolder-active-number nnfolder-current-group))))))
+       (goto-char end)))
+    (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
+    (current-buffer)))
+
+(defun nnfolder-get-new-mail ()
+  (let (incoming)
+    (if (and nnmail-spool-file
+            nnfolder-get-new-mail
+            (file-exists-p nnmail-spool-file)
+            (> (nth 7 (file-attributes nnmail-spool-file)) 0))
+       (progn
+         (and gnus-verbose-backends
+              (message "nnfolder: Reading incoming mail..."))
+         (setq incoming 
+               (nnmail-move-inbox nnmail-spool-file
+                                  (concat nnfolder-directory "Incoming")))
+         (nnmail-split-incoming incoming 'nnfolder-save-mail)
+         (run-hooks 'nnmail-read-incoming-hook)
+         (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
+         (and gnus-verbose-backends
+              (message "nnfolder: Reading incoming mail...done"))))
+    (let ((bufs nnfolder-buffer-alist))
+      (save-excursion
+       (while bufs
+         (if (not (buffer-name (nth 1 (car bufs))))
+             (setq nnfolder-buffer-alist 
+                   (delq (car bufs) nnfolder-buffer-alist))
+           (set-buffer (nth 1 (car bufs)))
+           (save-buffer))
+         (setq bufs (cdr bufs)))))
+    ;; (if incoming (delete-file incoming))
+    ))
+
+(provide 'nnfolder)
+
+;;; nnfolder.el ends here
index 4b01bca..52ed8e6 100644 (file)
@@ -2,7 +2,7 @@
 ;; Copyright (C) 1987,88,89,90,93,94,95 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
index ece1c4b..44eb20e 100644 (file)
@@ -1,7 +1,7 @@
 ;;;; nnkiboze.el --- select virtual news access for (ding) Gnus
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -90,7 +90,7 @@ If the stream is opened, return T, otherwise return NIL."
   (and nntp-server-buffer
        (get-buffer nntp-server-buffer)))
 
-(defun nnkiboze-status-message ()
+(defun nnkiboze-status-message (&optional server)
   "Return server status response as string."
   nnkiboze-status-string)
 
@@ -195,7 +195,7 @@ Finds out what articles are to be part of the nnkiboze groups."
        (gnus-read-active-file t)
        (gnus-expert-user t))
     (gnus))
-  (let* ((gnus-newsrc-assoc (copy-alist gnus-newsrc-assoc))
+  (let* ((gnus-newsrc-assoc (gnus-copy-sequence gnus-newsrc-assoc))
         (newsrc gnus-newsrc-assoc))
     (while newsrc
       (if (string-match "nnkiboze" (car (car newsrc)))
@@ -220,7 +220,9 @@ Finds out what articles are to be part of the nnkiboze groups."
     (setq nnkiboze-current-score-group group)
     (or info (error "No such group: %s" group))
     (and (file-exists-p newsrc-file) (load newsrc-file))
-    (setq nov-buffer (find-file-noselect nov-file))
+    (save-excursion
+      (set-buffer (setq nov-buffer (find-file-noselect nov-file)))
+      (buffer-disable-undo (current-buffer)))
     (mapatoms
      (lambda (group)
        (if (and (string-match regexp (setq gname (symbol-name group)))
index 0ba607f..f534862 100644 (file)
@@ -1,7 +1,7 @@
 ;;; nnmail.el --- mail support functions for the Gnus mail backends
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 (defvar nnmail-split-methods
   '(("mail.misc" ""))
-  "nnmail will split incoming mail into the groups detailed in this variable.")
+  "Incoming mail will be split according to this variable.
+
+If you'd like, for instance, one mail group for mail from the
+\"4ad-l\" mailing list, one group for junk mail and one for everything
+else, you could do something like this:
+
+ (setq nnmail-split-methods
+       '((\"mail.4ad\" \"From:.*4ad\")
+         (\"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,
+does not have to be called anything beginning with \"mail\",
+\"yonka.zow\" is a fine, fine name), and the second is a regexp that
+nnmail 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.
+
+The last element should always have \"\" as the regexp.")
 
 ;; Suggested by Erik Selberg <speed@cs.washington.edu>.
 (defvar nnmail-crosspost t
   "If non-nil, do crossposting if several split methods match the mail.
 If nil, the first match found will be used.")
 
+;; Added by gord@enci.ucalgary.ca (Gordon Matzigkeit).
+(defvar nnmail-keep-last-article nil
+  "If non-nil, nnmail will never delete the last expired article in a
+directory.  You may need to set this variable if other programs are putting
+new mail into folder numbers that Gnus has marked as expired.")
+
 (defvar nnmail-expiry-wait 7
   "Articles that are older than `nnmail-expiry-wait' days will be expired.")
 
@@ -95,10 +123,11 @@ messages will be shown to indicate the current status.")
 
 \f
 
-(defun nnmail-request-post-buffer (method header article-buffer group info)
+(defun nnmail-request-post-buffer (post group subject header article-buffer
+                                       info follow-to respect-poster)
   (let ((method-address (cdr (assq 'to-address (nth 4 info))))
        from subject date to reply-to message-of
-       references message-id sender follow-to cc)
+       references message-id sender cc)
     (setq method-address
          (if (and (stringp method-address) 
                   (string= method-address ""))
@@ -112,17 +141,14 @@ messages will be shown to indicate the current status.")
               (not (y-or-n-p "Unsent mail being composed; erase it? ")))
          ()
        (erase-buffer)
-       (if (eq method 'post)
-           (mail-setup method-address nil nil nil nil nil)
+       (if post
+           (mail-setup method-address subject nil nil nil nil)
          (save-excursion
            (set-buffer article-buffer)
            (goto-char (point-min))
            (narrow-to-region (point-min)
                              (progn (search-forward "\n\n") (point)))
            (set-text-properties (point-min) (point-max) nil)
-           (if (and (boundp 'gnus-followup-to-function)
-                    gnus-followup-to-function)
-               (setq follow-to (funcall gnus-followup-to-function group)))
            (setq from (header-from header))
            (setq date (header-date header))
            (and from
@@ -158,8 +184,7 @@ messages will be shown to indicate the current status.")
            (if message-id (insert message-id))
            ;; The region must end with a newline to fill the region
            ;; without inserting extra newline.
-           (fill-region-as-paragraph begin (1+ (point))))
-         ))
+           (fill-region-as-paragraph begin (1+ (point))))))
       (current-buffer))))
 
 (defun nnmail-find-file (file)
@@ -268,8 +293,9 @@ messages will be shown to indicate the current status.")
                                                      (point-max))))
                   (sit-for 3)
                   nil)))))
-    (if (buffer-name errors)
-       (kill-buffer errors))
+    (and errors
+        (buffer-name errors)
+        (kill-buffer errors))
     tofile))
 
 
@@ -375,9 +401,13 @@ FUNC will be called with the group name to determine the article number."
       (while (and methods (or nnmail-crosspost (not group-art)))
        (goto-char (point-max))
        (if (or (cdr methods)
-               (not (string= "" (nth 1 (car methods)))))
+               (not (equal "" (nth 1 (car methods)))))
            (if (and (condition-case () 
-                        (re-search-backward (car (cdr (car methods))) nil t)
+                        (if (stringp (nth 1 (car methods)))
+                            (re-search-backward
+                             (car (cdr (car methods))) nil t)
+                          ;; Suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
+                          (funcall (nth 1 (car methods)) (car (car methods))))
                       (error nil))
                     ;; Don't enter the article into the same group twice.
                     (not (assoc (car (car methods)) group-art)))
index a858930..175af1d 100644 (file)
@@ -1,7 +1,7 @@
 ;;; nnmbox.el --- mail mbox access for Gnus
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
@@ -122,7 +122,7 @@ If the stream is opened, return T, otherwise return NIL."
   (and nntp-server-buffer
        (get-buffer nntp-server-buffer)))
 
-(defun nnmbox-status-message ()
+(defun nnmbox-status-message (&optional server)
   "Return server status response as string."
   nnmbox-status-string)
 
@@ -137,8 +137,8 @@ If the stream is opened, return T, otherwise return NIL."
       (if (search-forward (nnmbox-article-string article) nil t)
          (let (start stop)
            (re-search-backward (concat "^" rmail-unix-mail-delimiter) nil t)
-           (forward-line 1)
            (setq start (point))
+           (forward-line 1)
            (or (and (re-search-forward 
                      (concat "^" rmail-unix-mail-delimiter) nil t)
                     (forward-line -1))
@@ -148,6 +148,11 @@ If the stream is opened, return T, otherwise return NIL."
              (set-buffer nntp-server-buffer)
              (erase-buffer)
              (insert-buffer-substring nnmbox-mbox-buffer start stop)
+             (goto-char (point-min))
+             (while (looking-at "From ")
+               (delete-char 5)
+               (insert "X-From-Line: ")
+               (forward-line 1))
              t))))))
 
 (defun nnmbox-request-group (group &optional server dont-check)
@@ -175,7 +180,11 @@ If the stream is opened, return T, otherwise return NIL."
 (defun nnmbox-request-list (&optional server)
   "List active newsgoups."
   (if server (nnmbox-get-new-mail))
-  (nnmail-find-file nnmbox-active-file))
+  (or (nnmail-find-file nnmbox-active-file)
+      (progn
+       (setq nnmbox-group-alist (nnmail-get-active))
+       (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
+       (nnmail-find-file nnmbox-active-file))))
 
 (defun nnmbox-request-newgroups (date &optional server)
   "List groups created after DATE."
@@ -223,7 +232,8 @@ the date."
       (save-buffer)
       rest)))
 
-(defun nnmbox-request-move-article (article group server accept-form)
+(defun nnmbox-request-move-article
+  (article group server accept-form &optional last)
   (nnmbox-possibly-change-newsgroup group)
   (let ((buf (get-buffer-create " *nnmbox move*"))
        result)
@@ -231,47 +241,52 @@ the date."
      (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))
-       (if (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))))
+       (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))))
        (setq result (eval accept-form))
-       (kill-buffer (current-buffer))
+       (kill-buffer buf)
        result)
      (save-excursion
        (set-buffer nnmbox-mbox-buffer)
        (goto-char 1)
        (if (search-forward (nnmbox-article-string article) nil t)
           (nnmbox-delete-mail))
-       (save-buffer)))
+       (and last (save-buffer))))
     result))
 
-(defun nnmbox-request-accept-article (group)
+(defun nnmbox-request-accept-article (group &optional last)
   (let ((buf (current-buffer))
        result beg)
+    (debug (current-buffer))
+    (goto-char (point-min))
+    (if (looking-at "X-From-Line: ")
+       (replace-match "From ")
+      (insert "From nobody " (current-time-string) "\n"))
     (and 
+     (nnmbox-request-list)
      (setq nnmbox-group-alist (nnmail-get-active))
+     (progn
+       (set-buffer buf)
+       (goto-char (point-min))
+       (search-forward "\n\n" nil t)
+       (forward-line -1)
+       (while (re-search-backward "^X-Gnus-Newsgroup: " nil t)
+        (delete-region (point) (progn (forward-line 1) (point))))
+       (setq result (nnmbox-save-mail (and (stringp group) group))))
      (save-excursion
        (set-buffer nnmbox-mbox-buffer)
-       (setq beg (goto-char (point-max)))
        (insert-buffer-substring buf)
-       (goto-char beg)
-       (if (stringp group)
-          (progn
-            (search-forward "\n\n" nil t)
-            (forward-line -1)
-            (save-excursion
-              (while (re-search-backward "^X-Gnus-Newsgroup: " beg t)
-                (delete-region (point) (progn (forward-line 1) (point)))))
-            (setq result (nnmbox-insert-newsgroup-line group)))
-        (setq result (nnmbox-save-mail)))
-       (save-buffer)
+       (and last (save-buffer))
        result)
      (nnmail-save-active nnmbox-group-alist nnmbox-active-file))
-    result))
+    (car result)))
 
 (defun nnmbox-request-replace-article (article group buffer)
   (nnmbox-possibly-change-newsgroup group)
@@ -286,7 +301,7 @@ the date."
       t)))
 
 \f
-;;; Low-Level Interface
+;;; Internal functions.
 
 (defun nnmbox-delete-mail (&optional force leave-delim)
   "If FORCE, delete article no matter how many X-Gnus-Newsgroup
@@ -325,21 +340,26 @@ delimeter line."
                          (find-file-noselect nnmbox-mbox-file)))
        (buffer-disable-undo (current-buffer))))
   (if (not nnmbox-group-alist)
-      (setq nnmbox-group-alist (nnmail-get-active)))
+      (progn
+       (nnmbox-request-list)
+       (setq nnmbox-group-alist (nnmail-get-active))))
   (if newsgroup
       (if (assoc newsgroup nnmbox-group-alist)
          (setq nnmbox-current-group newsgroup))))
 
 (defun nnmbox-article-string (article)
   (concat "\nX-Gnus-Newsgroup: " nnmbox-current-group ":" 
-         (int-to-string article)))
+         (int-to-string article) " "))
 
-(defun nnmbox-save-mail ()
+(defun nnmbox-save-mail (&optional group)
   "Called narrowed to an article."
-  (let ((group-art (nreverse (nnmail-article-group 'nnmbox-active-number))))
+  (let* ((nnmail-split-methods 
+         (if group (list (list group "")) nnmail-split-methods))
+        (group-art (nreverse (nnmail-article-group 'nnmbox-active-number))))
     (nnmail-insert-lines)
     (nnmail-insert-xref group-art)
-    (nnmbox-insert-newsgroup-line group-art)))
+    (nnmbox-insert-newsgroup-line group-art)
+    group-art))
 
 (defun nnmbox-insert-newsgroup-line (group-art)
   (save-excursion
@@ -351,7 +371,8 @@ delimeter line."
            (insert (format "X-Gnus-Newsgroup: %s:%d   %s\n" 
                            (car (car group-art)) (cdr (car group-art))
                            (current-time-string)))
-           (setq group-art (cdr group-art)))))))
+           (setq group-art (cdr group-art)))))
+    t))
 
 (defun nnmbox-active-number (group)
   "Find the next article number in GROUP."
@@ -398,7 +419,7 @@ delimeter line."
 (defun nnmbox-get-new-mail ()
   (let (incoming)
     (nnmbox-read-mbox)
-    (if (and nnmail-spool-file
+    (if (and nnmail-spool-file nnmbox-get-new-mail
             (file-exists-p nnmail-spool-file)
             (> (nth 7 (file-attributes nnmail-spool-file)) 0))
        (progn
index e42f3fb..0ba5266 100644 (file)
@@ -1,7 +1,7 @@
 ;;; nnmh.el --- mail spool access for Gnus (mhspool)
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
@@ -115,7 +115,7 @@ If the stream is opened, return T, otherwise return NIL."
   (and nntp-server-buffer
        (get-buffer nntp-server-buffer)))
 
-(defun nnmh-status-message ()
+(defun nnmh-status-message (&optional server)
   "Return server status response as string."
   nnmh-status-string)
 
@@ -219,6 +219,11 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
                        (funcall nnmail-expiry-wait-function newsgroup))
                   nnmail-expiry-wait))
         article rest mod-time)
+    (if nnmail-keep-last-article
+       (progn
+         (setq articles (sort articles '>))
+         (setq rest (cons (car articles) rest))
+         (setq articles (cdr articles))))
     (while articles
       (setq article (concat nnmh-current-directory (int-to-string
                                                    (car articles))))
@@ -240,7 +245,8 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
 (defun nnmh-close-group (group &optional server)
   t)
 
-(defun nnmh-request-move-article (article group server accept-form)
+(defun nnmh-request-move-article 
+  (article group server accept-form &optional last)
   (let ((buf (get-buffer-create " *nnmh move*"))
        result)
     (and 
@@ -257,7 +263,7 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
        (file-error nil)))
  result))
 
-(defun nnmh-request-accept-article (group)
+(defun nnmh-request-accept-article (group &optional last)
   (if (stringp group)
       (and 
        (nnmh-request-list)
index f611fa6..7ade6d8 100644 (file)
@@ -1,7 +1,7 @@
 ;;; nnml.el --- mail spool access for Gnus
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
@@ -64,6 +64,7 @@ all. This may very well take some time.")
 (defvar nnml-nov-buffer-alist nil)
 
 (defvar nnml-group-alist nil)
+(defvar nnml-active-timestamp nil)
 
 \f
 
@@ -133,7 +134,7 @@ If the stream is opened, return T, otherwise return NIL."
   (and nntp-server-buffer
        (get-buffer nntp-server-buffer)))
 
-(defun nnml-status-message ()
+(defun nnml-status-message (&optional server)
   "Return server status response as string."
   nnml-status-string)
 
@@ -152,22 +153,31 @@ If the stream is opened, return T, otherwise return NIL."
 
 (defun nnml-request-group (group &optional server dont-check)
   "Select news GROUP."
-  (nnml-possibly-change-directory group)
-  (or dont-check (nnml-get-new-mail))
-  (or nnml-group-alist 
+  (if (not (nnml-possibly-change-directory group))
       (progn
-       (nnml-request-list)
-       (setq nnml-group-alist (nnmail-get-active))))
-  (let ((active (nth 1 (assoc group nnml-group-alist))))
-    (save-excursion
-      (set-buffer nntp-server-buffer)
-      (erase-buffer)
-      (if (not active)
-         ()
-       (insert (format "211 %d %d %d %s\n" 
-                       (max (1+ (- (cdr active) (car active))) 0)
-                       (car active) (cdr active) group))
-       t))))
+       (setq nnml-status-string "Invalid group (no such directory)")
+       nil)
+    (if dont-check 
+       t
+      (nnml-get-new-mail)
+      (let ((timestamp (nth 5 (file-attributes nnml-active-file))))
+       (if (or (not nnml-active-timestamp)
+               (> (nth 0 timestamp) (nth 0 nnml-active-timestamp))
+               (> (nth 1 timestamp) (nth 1 nnml-active-timestamp)))
+           (progn
+             (setq nnml-active-timestamp timestamp)
+             (nnml-request-list)
+             (setq nnml-group-alist (nnmail-get-active))))
+       (let ((active (nth 1 (assoc group nnml-group-alist))))
+         (save-excursion
+           (set-buffer nntp-server-buffer)
+           (erase-buffer)
+           (if (not active)
+               ()
+             (insert (format "211 %d %d %d %s\n" 
+                             (max (1+ (- (cdr active) (car active))) 0)
+                             (car active) (cdr active) group))
+             t)))))))
 
 (defun nnml-close-group (group &optional server)
   t)
@@ -203,6 +213,11 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
                        (funcall nnmail-expiry-wait-function newsgroup))
                   nnmail-expiry-wait))
         article rest mod-time)
+    (if nnmail-keep-last-article
+       (progn
+         (setq articles (sort articles '>))
+         (setq rest (cons (car articles) rest))
+         (setq articles (cdr articles))))
     (while articles
       (setq article (concat nnml-current-directory (int-to-string
                                                      (car articles))))
@@ -223,7 +238,8 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
     (nnml-save-nov)
     rest))
 
-(defun nnml-request-move-article (article group server accept-form)
+(defun nnml-request-move-article 
+  (article group server accept-form &optional last)
   (let ((buf (get-buffer-create " *nnml move*"))
        result)
     (and 
@@ -240,10 +256,10 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
                                (int-to-string article)))
         (file-error nil))
        (nnml-nov-delete-article group article)
-       (nnml-save-nov)))
+       (and last (nnml-save-nov))))
     result))
 
-(defun nnml-request-accept-article (group)
+(defun nnml-request-accept-article (group &optional last)
   (let (result)
     (if (stringp group)
        (and 
@@ -255,14 +271,14 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
           (setq result (car (nnml-save-mail))))
         (progn
           (nnmail-save-active nnml-group-alist nnml-active-file)
-          (nnml-save-nov)))
+          (and last (nnml-save-nov))))
       (and
        (nnml-request-list)
        (setq nnml-group-alist (nnmail-get-active))
        (setq result (car (nnml-save-mail)))
        (progn
         (nnmail-save-active nnml-group-alist nnml-active-file)
-        (nnml-save-nov))))
+        (and last (nnml-save-nov)))))
     result))
 
 (defun nnml-request-replace-article (article group buffer)
@@ -325,10 +341,10 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
 (defun nnml-possibly-change-directory (newsgroup)
   (if newsgroup
       (let ((pathname (nnmail-article-pathname newsgroup nnml-directory)))
-       (if (file-directory-p pathname)
-           (setq nnml-current-directory pathname)
-         (error "No such newsgroup: %s" newsgroup)))))
-
+       (and (file-directory-p pathname)
+            (setq nnml-current-directory pathname)))
+    t))
+            
 (defun nnml-create-directories ()
   (let ((methods nnmail-split-methods)
        dir dirs)
@@ -504,11 +520,14 @@ If FORCE is non-nil, ARTICLES will be deleted whether they are old or not."
       (if (buffer-name (cdr (car nnml-nov-buffer-alist)))
          (progn
            (set-buffer (cdr (car nnml-nov-buffer-alist)))
-           (write-region 1 (point-max) (buffer-file-name) nil 'nomesg)
+           (and (buffer-modified-p)
+                (write-region 
+                 1 (point-max) (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 (dir)
   "Generate nov databases in all nnml mail newsgroups."
   (interactive 
index 632b646..16f2ae8 100644 (file)
@@ -2,7 +2,7 @@
 ;; Copyright (C) 1988,89,90,93,94,95 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Commentary:
 
-;; All the Gnus backends have the same interface, and should return
-;; data in a similar format. Below is an overview of what functions
-;; these packages must supply and what results they should return.
-;;
-;; Variables:
-;;
-;; `nntp-server-buffer' - All data should be returned to Gnus in this
-;; buffer. 
-;;
-;; Functions for the imaginary backend `choke':
-;;
-;; `choke-retrieve-headers ARTICLES &optional GROUP SERVER'
-;; Should return all headers for all ARTICLES, or return NOV lines for
-;; the same.
-;;
-;; `choke-request-group GROUP &optional SERVER DISCARD'
-;; Switch to GROUP. If DISCARD is nil, active information on the group
-;; must be returned.
-;;
-;; `choke-close-group GROUP &optional SERVER'
-;; Close group. Most backends won't have to do anything with this
-;; call, but it is an opportunity to clean up, if that is needed. It
-;; is called when Gnus exits a group.
-;;
-;; `choke-request-article ARTICLE &optional GROUP SERVER'
-;; Return ARTICLE, which is either an article number or
-;; message-id. Note that not all backends can return articles based on
-;; message-id. 
-;;
-;; `choke-request-list SERVER'
-;; Return a list of all active newsgroups on SERVER.
-;;
-;; `choke-request-list-newsgroups SERVER'
-;; Return a list of descriptions of all newsgroups on SERVER.
-;;
-;; `choke-request-newgroups DATE &optional SERVER'
-;; Return a list of all groups that have arrived after DATE on
-;; SERVER. Note that the date doesn't have to be respected - Gnus will
-;; always check whether the groups are old or not. Backends that do
-;; not store date information may just return the entire list of
-;; groups. 
-;;
-;; `choke-request-post-buffer METHOD HEADER ARTICLE-BUFFER GROUP INFO'
-;; Should return a buffer that is suitable for "posting". nnspool and
-;; nntp return a `*post-buffer*', and nnmail return a `*mail*'
-;; buffer. This function should fill out the appropriate headers. 
-;;
-;; `choke-request-post &optional SERVER'
-;; Function that will be called from a buffer to be posted. 
-;;
-;; `choke-open-server SERVER &optional ARGUMENT'
-;; Open a connection to SERVER.
-;;
-;; `choke-close-server &optional SERVER'
-;; Close the connection to SERVER.
-;;
-;; `choke-server-opened &optional SERVER'
-;; Whether the conenction to SERVER is opened or not.
-;;
-;; `choke-server-status &optional SERVER'
-;; Should return a status string (not in the nntp buffer, but as the
-;; result of the function).
-;;
-;; The following functions are optional and apply only to backends
-;; that are able to control the contents of their groups totally
-;; (ie. mail backends.)  Backends that aren't able to do that
-;; shouldn't define these functions at all. Gnus will check for their
-;; presence before attempting to call them.
-;;
-;; `choke-request-expire-articles ARTICLES &optional NEWSGROUP SERVER'
-;; Should expire (according to some aging scheme) all ARTICLES. Most
-;; backends will not be able to expire articles. Should return a list
-;; of all articles that were not expired.
-;;
-;; `choke-request-move-article ARTICLE GROUP SERVER ACCEPT-FORM'
-;; Should move ARTICLE from GROUP on SERVER by using ACCEPT-FORM.
-;; Removes any information it has added to the article (extra headers,
-;; whatever - make it as clean as possible), and then passes the
-;; article on by evaling ACCEPT-FORM, which is normally a call to the
-;; function described below. If the ACCEPT-FORM returns a non-nil
-;; value, the article should then be deleted.
-;;
-;; `choke-request-accept-article GROUP'
-;; The contents of the current buffer will be put into GROUP. There
-;; should, of course, be an article in the current buffer. This
-;; function is normally only called by the function described above. 
-;;
-;; `choke-request-replace-article ARTICLE GROUP BUFFER'
-;; Replace ARTICLE in GROUP with the contents of BUFFER.
-;; This provides an easy interface for allowing editing of
-;; articles. Note that even headers may be edited, so the backend has
-;; to update any tables (nov buffers, etc) that it maintains after
-;; replacing the article.
-;;
-;; All these functions must return nil if they couldn't service the
-;; request. If the optional arguments are not supplied, some "current"
-;; or "default" values should be used. In short, one should emulate an
-;; NNTP server, in a way.
-;;
-;; If you want to write a new backend, you just have to supply the
-;; functions listed above. In addition, you must enter the new backend
-;; into the list of valid select methods:
-;; (setq gnus-valid-select-methods 
-;;       (cons '("choke" mail) gnus-valid-select-methods))
-;; The first element in this list is the name of the backend. Other
-;; elemnets may be `mail' (for mail groups),  `post' (for news
-;; groups), `none' (neither), `respool' (for groups that can control
-;; their contents). 
-
 ;;; Code:
 
 (require 'nnheader)
 (require 'nntp)
+(require 'timezone)
 
 (defvar nnspool-inews-program news-inews-program
   "Program to post news.")
 (defvar nnspool-spool-directory news-path
   "Local news spool directory.")
 
+(defvar nnspool-nov-directory (concat nnspool-spool-directory "over.view/")
+  "Local news nov directory.")
+
 (defvar nnspool-lib-dir "/usr/lib/news/"
   "Where the local news library files are stored.")
 
@@ -180,6 +75,7 @@ messages will be shown to indicate the current status.")
 (defvar nnspool-current-directory nil
   "Current news group directory.")
 
+(defvar nnspool-current-group nil)
 (defvar nnspool-status-string "")
 
 \f
@@ -197,37 +93,38 @@ Newsgroup must be selected before calling this function."
           (do-message (and (numberp nnspool-large-newsgroup)
                            (> number nnspool-large-newsgroup)))
           file beg article)
-      (nnspool-possibly-change-directory newsgroup)
-      (if (nnspool-retrieve-headers-with-nov sequence)
-         'nov
-       (while sequence
-         (setq article (car sequence))
-         (setq file (concat nnspool-current-directory 
-                            (int-to-string article)))
-         (and (file-exists-p file)
-              (progn
-                (insert (format "221 %d Article retrieved.\n" article))
-                (setq beg (point))
-                (insert-file-contents file)
-                (goto-char beg)
-                (search-forward "\n\n" nil t)
-                (forward-char -1)
-                (insert ".\n")
-                (delete-region (point) (point-max))))
-         (setq sequence (cdr sequence))
-
-         (and do-message
-              (zerop (% (setq count (1+ count)) 20))
-              (message "NNSPOOL: Receiving headers... %d%%"
-                       (/ (* count 100) number))))
-
-       (and do-message (message "NNSPOOL: Receiving headers... done"))
-
-       ;; Fold continuation lines.
-       (goto-char 1)
-       (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-         (replace-match " " t t))
-       'headers))))
+      (if (not (nnspool-possibly-change-directory newsgroup))
+         ()
+       (if (nnspool-retrieve-headers-with-nov sequence)
+           'nov
+         (while sequence
+           (setq article (car sequence))
+           (setq file (concat nnspool-current-directory 
+                              (int-to-string article)))
+           (and (file-exists-p file)
+                (progn
+                  (insert (format "221 %d Article retrieved.\n" article))
+                  (setq beg (point))
+                  (insert-file-contents file)
+                  (goto-char beg)
+                  (search-forward "\n\n" nil t)
+                  (forward-char -1)
+                  (insert ".\n")
+                  (delete-region (point) (point-max))))
+           (setq sequence (cdr sequence))
+           
+           (and do-message
+                (zerop (% (setq count (1+ count)) 20))
+                (message "NNSPOOL: Receiving headers... %d%%"
+                         (/ (* count 100) number))))
+         
+         (and do-message (message "NNSPOOL: Receiving headers... done"))
+         
+         ;; Fold continuation lines.
+         (goto-char 1)
+         (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
+           (replace-match " " t t))
+         'headers)))))
 
 (defun nnspool-open-server (host &optional service)
   "Open local spool."
@@ -248,9 +145,9 @@ Newsgroup must be selected before calling this function."
   "Return server process status, T or NIL.
 If the stream is opened, return T, otherwise return NIL."
   (and nntp-server-buffer
-       (get-buffer nntp-server-buffer)))
+       (buffer-name nntp-server-buffer)))
 
-(defun nnspool-status-message ()
+(defun nnspool-status-message (&optional server)
   "Return server status response as string."
   nnspool-status-string)
 
@@ -294,34 +191,38 @@ If the stream is opened, return T, otherwise return NIL."
   (let ((pathname (nnspool-article-pathname
                   (nnspool-replace-chars-in-string group ?. ?/)))
        dir)
-    (if (file-directory-p pathname)
+    (if (not (file-directory-p pathname))
        (progn
-         (setq nnspool-current-directory pathname)
-         (if (not dont-check)
-             (progn
-               (setq dir (directory-files pathname nil "^[0-9]+$" t))
-               ;; yes, completely empty spool directories *are* possible
-               ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>
-               (and dir
-                   (setq dir
-                         (sort 
-                          (mapcar
-                           (function
-                            (lambda (name)
-                              (string-to-int name)))
-                           dir)
-                          '<)))
-               (save-excursion
-                 (set-buffer nntp-server-buffer)
-                 (erase-buffer)
-                 (if dir
-                     (insert
-                      (format "211 %d %d %d %s\n" (length dir) (car dir)
-                              (progn (while (cdr dir) (setq dir (cdr dir)))
-                                     (car dir))
-                              group))
-                   (insert (format "211 0 0 0 %s\n" group))))))
-         t))))
+         (setq nnspool-status-string
+               "Invalid group name (no such directory)")
+         nil)
+      (setq nnspool-current-directory pathname)
+      (setq nnspool-status-string "")
+      (if (not dont-check)
+         (progn
+           (setq dir (directory-files pathname nil "^[0-9]+$" t))
+           ;; yes, completely empty spool directories *are* possible
+           ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>
+           (and dir
+                (setq dir
+                      (sort 
+                       (mapcar
+                        (function
+                         (lambda (name)
+                           (string-to-int name)))
+                        dir)
+                       '<)))
+           (save-excursion
+             (set-buffer nntp-server-buffer)
+             (erase-buffer)
+             (if dir
+                 (insert
+                  (format "211 %d %d %d %s\n" (length dir) (car dir)
+                          (progn (while (cdr dir) (setq dir (cdr dir)))
+                                 (car dir))
+                          group))
+               (insert (format "211 0 0 0 %s\n" group))))))
+      t)))
 
 (defun nnspool-close-group (group &optional server)
   t)
@@ -341,11 +242,38 @@ If the stream is opened, return T, otherwise return NIL."
   (save-excursion
     (nnspool-find-file nnspool-distributions-file)))
 
+;; Suggested by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
 (defun nnspool-request-newgroups (date &optional server)
   "List groups created after DATE."
-  (save-excursion
-    (nnspool-find-file nnspool-active-times-file)
-    (setq nnspool-status-string "NEWGROUPS is not supported.")
+  (if (nnspool-find-file nnspool-active-times-file)
+      (save-excursion
+       ;; Find the last valid line.
+       (goto-char (point-max))
+       (while (and (not (looking-at 
+                         "\\([^ ]+\\) +\\([0-9]+\\)[0-9][0-9][0-9] "))
+                   (zerop (forward-line -1))))
+       (let ((seconds (nnspool-date-to-seconds date))
+             groups)
+         ;; Go through lines and add groups that are recent to a list.
+         (while (and (looking-at "\\([^ ]+\\) +\\([0-9]+\\)[0-9][0-9][0-9] ")
+                     ;; We ignore the last three digits in the number
+                     ;; of seconds. This is quite naughty, but large
+                     ;; numbers are so tiresome to deal with. Perhaps
+                     ;; one could switch to floats instead? 
+                     (> (save-restriction 
+                          (goto-char (match-beginning 2))
+                          (narrow-to-region (point) (match-end 2))
+                          (read (current-buffer)))
+                        seconds)
+                     (setq groups (cons (buffer-substring
+                                         (match-beginning 1) (match-end 1))
+                                        groups))
+                     (zerop (forward-line -1))))
+         (erase-buffer)
+         (while groups
+           (insert (car groups) " 0 0 y\n")
+           (setq groups (cdr groups))))
+       t)
     nil))
 
 (defun nnspool-request-post (&optional server)
@@ -378,7 +306,10 @@ If the stream is opened, return T, otherwise return NIL."
 (defun nnspool-retrieve-headers-with-nov (articles)
   (if (or gnus-nov-is-evil nnspool-nov-is-evil)
       nil
-    (let ((nov (concat nnspool-current-directory ".overview"))
+    (let ((nov (concat nnspool-nov-directory
+                      (nnspool-replace-chars-in-string
+                       nnspool-current-group ?. ?/)
+                      "/.overview"))
          article)
       (if (file-exists-p nov)
          (save-excursion
@@ -391,7 +322,7 @@ If the stream is opened, return T, otherwise return NIL."
            ;; we find one of the articles we want.
            (while (and articles
                        (setq article (concat (int-to-string 
-                                              (car articles) "\t")))
+                                              (car articles)) "\t"))
                        (not (or (looking-at article)
                                 (search-forward (concat "\n" article) 
                                                 nil t))))
@@ -447,8 +378,13 @@ If the stream is opened, return T, otherwise return NIL."
       (let ((pathname (nnspool-article-pathname
                       (nnspool-replace-chars-in-string newsgroup ?. ?/))))
        (if (file-directory-p pathname)
-           (setq nnspool-current-directory pathname)
-         (error "No such newsgroup: %s" newsgroup)))))
+           (progn
+             (setq nnspool-current-directory pathname)
+             (setq nnspool-current-group newsgroup))
+         (setq nnspool-status-string 
+               (format "No such newsgroup: %s" newsgroup))
+         nil))
+    t))
 
 (defun nnspool-article-pathname (group)
   "Make pathname for GROUP."
@@ -466,6 +402,35 @@ If the stream is opened, return T, otherwise return NIL."
       (setq idx (1+ idx)))
     string))
 
+(defun nnspool-number-base-10 (num pos)
+  (if (<= pos 0) ""
+    (setcdr num (+ (* (% (car num) 10) 65536) (cdr num)))
+    (apply
+     'concat
+     (reverse
+      (list
+       (char-to-string
+       (aref "0123456789" (% (cdr num) 10)))
+       (progn
+        (setcdr num (/ (cdr num) 10))
+        (setcar num (/ (car num) 10))
+        (nnspool-number-base-10 num (1- pos))))))))
+
+(defun nnspool-days-between (date1 date2)
+  ;; Return the number of days between date1 and date2.
+  (let ((d1 (mapcar (lambda (s) (and s (string-to-int s)))
+                   (timezone-parse-date date1)))
+       (d2 (mapcar (lambda (s) (and s (string-to-int s)))
+                   (timezone-parse-date date2))))
+    (- (timezone-absolute-from-gregorian 
+       (nth 1 d1) (nth 2 d1) (car d1))
+       (timezone-absolute-from-gregorian 
+       (nth 1 d2) (nth 2 d2) (car d2)))))
+
+(defun nnspool-date-to-seconds (string)
+  (let ((days (nnspool-days-between string "Jan 1 00:00:00 1970")))
+    (* days 86)))
+
 (provide 'nnspool)
 
 ;;; nnspool.el ends here
index ef40220..b4ed194 100644 (file)
@@ -2,7 +2,7 @@
 ;; Copyright (C) 1987,88,89,90,92,93,94,95 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -30,7 +30,9 @@
 
 (eval-and-compile
   (autoload 'news-setup "rnewspost")
-  (autoload 'news-reply-mode "rnewspost"))
+  (autoload 'news-reply-mode "rnewspost")
+  (autoload 'nnmail-request-post-buffer "nnmail")
+  (autoload 'cancel-timer "timer"))
 
 (defvar nntp-server-hook nil
   "Hooks for the NNTP server.
@@ -48,14 +50,14 @@ server must be specified as follows:
 If you'd like to change something depending on the server in this
 hook, use the variable `nntp-server-name'.")
 
-(defvar nntp-server-opened-hook 
-  (list
-   (lambda ()
-     (nntp-send-command "MODE" "READER")))
-  "Hook used for sending commands to the server at startup.
-It is used by default to send the \"MODE READER\" command to the
-server. This makes innd servers spawn an nnrpd server.
-Other useful commands might be \"AUTHINFO\".")
+(defvar nntp-server-opened-hook nil
+  "Hook used for sending commands to the server at startup.  The
+default value is `nntp-send-mode-reader', whick 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.")
+(add-hook 'nntp-server-opened-hook 'nntp-send-mode-reader)
 
 (defvar nntp-large-newsgroup 50
   "The number of the articles which indicates a large newsgroup.
@@ -87,19 +89,23 @@ The strings are tried in turn until a positive response is gotten. If
 none of the commands are successful, nntp will just grab headers one
 by one.")
 
+(defvar 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.")
+
 \f
 (defconst nntp-version "nntp 4.0"
   "Version numbers of this version of NNTP.")
 
 (defvar nntp-server-name nil
-  "The name of the host running NNTP server.")
+  "The name of the NNTP server.")
 
 (defvar nntp-server-buffer nil
-  "Buffer associated with NNTP server process.")
+  "Buffer associated with the NNTP server process.")
 
 (defvar nntp-server-process nil
   "The NNTP server process.
-You'd better not use this variable in NNTP front-end program but
+You'd better not use this variable in NNTP front-end program, but
 instead use `nntp-server-buffer'.")
 
 (defvar nntp-status-string nil
@@ -108,11 +114,8 @@ You'd better not use this variable in NNTP front-end program but
 instead call function `nntp-status-message' to get status message.")
 
 (defvar nntp-current-server "")
-
 (defvar nntp-server-alist nil)
-
 (defvar nntp-server-xover t)
-
 (defvar nntp-current-group "")
 
 ;;; Interface funtions.
@@ -156,9 +159,7 @@ instead call function `nntp-status-message' to get status message.")
                       (zerop (% received 20))
                       (message "NNTP: Receiving headers... %d%%"
                                (/ (* received 100) number)))
-                 (nntp-accept-response))
-               ))
-         )
+                 (nntp-accept-response)))))
        ;; Wait for text of last command.
        (goto-char (point-max))
        (re-search-backward "^[0-9]" nil t)
@@ -188,31 +189,30 @@ instead call function `nntp-status-message' to get status message.")
 If SERVER is nil, use value of environment variable `NNTPSERVER'.
 If optional argument SERVICE is non-nil, open by the service name."
   (let ((server (or server (getenv "NNTPSERVER")))
-       (status nil))
+       (status nil)
+       (timer 
+        (and nntp-connection-timeout 
+             (run-at-time nntp-connection-timeout
+                          nil 'nntp-kill-connection server))))
     (setq nntp-status-string "")
     (message "nntp: Connecting to server on %s..." server)
     (cond ((and server (nntp-open-server-internal server service))
           (setq nntp-current-server server)
-          (setq status (nntp-wait-for-response "^[23].*\r$"))
-          ;; Do check unexpected close of connection.
-          ;; Suggested by feldmark@hanako.stars.flab.fujitsu.junet.
-          (if status
-              (progn
-                (set-process-sentinel nntp-server-process
-                                      'nntp-default-sentinel)
-                ;; You can send commands at startup like AUTHINFO here.
-                ;; Added by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>
-                (run-hooks 'nntp-server-opened-hook))
-            ;; We have to close connection here, since function
-            ;;  `nntp-server-opened' may return incorrect status.
-            (nntp-close-server-internal server)
-            ))
+          (condition-case nil
+              (setq status (nntp-wait-for-response "^[23].*\r$"))
+            (error (nntp-close-server-internal server)))
+          (and nntp-server-process
+               (progn
+                 (set-process-sentinel 
+                  nntp-server-process 'nntp-default-sentinel)
+                 ;; You can send commands at startup like AUTHINFO here.
+                 ;; Added by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>
+                 (run-hooks 'nntp-server-opened-hook))))
          ((null server)
-          (setq nntp-status-string "NNTP server is not specified."))
-         )
+          (setq nntp-status-string "NNTP server is not specified.")))
+    (and timer (cancel-timer timer))
     (message "")
-    status
-    ))
+    status))
 
 (defun nntp-close-server (&optional server)
   "Close news server."
@@ -226,10 +226,8 @@ If optional argument SERVICE is non-nil, open by the service name."
             (set-process-sentinel nntp-server-process nil))
        ;; We cannot send QUIT command unless the process is running.
        (if (nntp-server-opened)
-           (nntp-send-command nil "QUIT"))
-       )
-    (nntp-close-server-internal server)
-    ))
+           (nntp-send-command nil "QUIT")))
+    (nntp-close-server-internal server)))
 
 (fset 'nntp-request-quit (symbol-function 'nntp-close-server))
 
@@ -250,8 +248,7 @@ If the stream is opened, return non-nil, otherwise return nil."
                         nntp-status-string))
       (substring nntp-status-string (match-beginning 1) (match-end 1))
     ;; Empty message if nothing.
-    ""
-    ))
+    nntp-status-string))
 
 (defun nntp-request-article (id &optional newsgroup server buffer)
   "Select article by message ID (or number)."
@@ -272,16 +269,14 @@ If the stream is opened, return non-nil, otherwise return nil."
   (prog1
       ;; If NEmacs, end of message may look like: "\256\215" (".^M")
       (nntp-send-command "^\\.\r$" "BODY" id)
-    (nntp-decode-text)
-    ))
+    (nntp-decode-text)))
 
 (defun nntp-request-head (id &optional newsgroup server)
   "Select article head by message ID (or number)."
   (nntp-possibly-change-server newsgroup server)
   (prog1
       (nntp-send-command "^\\.\r$" "HEAD" id)
-    (nntp-decode-text)
-    ))
+    (nntp-decode-text)))
 
 (defun nntp-request-stat (id &optional newsgroup server)
   "Select article by message ID (or number)."
@@ -291,9 +286,12 @@ If the stream is opened, return non-nil, otherwise return nil."
 (defun nntp-request-group (group &optional server dont-check)
   "Select news GROUP."
   (if (nntp-possibly-change-server nil server)
-      (progn
-       (nntp-send-command "^.*\r$" "GROUP" group)
-       )))
+      (nntp-send-command "^.*\r$" "GROUP" group)))
+
+(defun nntp-request-group-description (group &optional server)
+  "Select news GROUP."
+  (if (nntp-possibly-change-server nil server)
+      (nntp-send-command "^.*\r$" "XGTITLE" group)))
 
 (defun nntp-close-group (group &optional server)
   t)
@@ -303,31 +301,34 @@ If the stream is opened, return non-nil, otherwise return nil."
   (nntp-possibly-change-server nil server)
   (prog1
       (nntp-send-command "^\\.\r$" "LIST")
-    (nntp-decode-text)
-    ))
+    (nntp-decode-text)))
 
 (defun nntp-request-list-newsgroups (&optional server)
   "List newsgroups (defined in NNTP2)."
   (nntp-possibly-change-server nil server)
   (prog1
       (nntp-send-command "^\\.\r$" "LIST NEWSGROUPS")
-    (nntp-decode-text)
-    ))
+    (nntp-decode-text)))
 
 (defun nntp-request-newgroups (date &optional server)
   "List new groups (defined in NNTP2)."
   (nntp-possibly-change-server nil server)
-  (prog1
-      (nntp-send-command "^\\.\r$" "NEWGROUPS" date)
-    (nntp-decode-text)))
+  (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$" "NEWGROUPS" time-string)
+      (nntp-decode-text))))
 
 (defun nntp-request-list-distributions (&optional server)
   "List distributions (defined in NNTP2)."
   (nntp-possibly-change-server nil server)
   (prog1
       (nntp-send-command "^\\.\r$" "LIST DISTRIBUTIONS")
-    (nntp-decode-text)
-    ))
+    (nntp-decode-text)))
 
 (defun nntp-request-last (&optional newsgroup server)
   "Set current article pointer to the previous article
@@ -349,90 +350,100 @@ in the current news group."
        (nntp-send-region-to-server (point-min) (point-max))
        ;; 1.2a NNTP's post command is buggy. "^M" (\r) is not
        ;;  appended to end of the status message.
-       (nntp-wait-for-response "^[23].*$")
-       )))
-
-(defun nntp-request-post-buffer (method header article-buffer group info)
-  (let (from subject date to followup-to newsgroups message-of
-            references distribution message-id follow-to)
-    (save-excursion
-      (set-buffer (get-buffer-create "*post-news*"))
-      (news-reply-mode)
-      (if (and (buffer-modified-p)
-              (> (buffer-size) 0)
-              (not (y-or-n-p "Unsent article being composed; erase it? ")))
-         ()
-       (erase-buffer)
-       (if (eq method 'post)
-           (news-setup nil nil nil header article-buffer)
-         (save-excursion
-           (set-buffer article-buffer)
-           (goto-char (point-min))
-           (narrow-to-region (point-min)
-                             (progn (search-forward "\n\n") (point)))
-           (if (and (boundp 'gnus-followup-to-function)
-                    gnus-followup-to-function)
-               (setq follow-to (funcall gnus-followup-to-function group)))
-           (setq from (header-from header))
-           (setq date (header-date header))
-           (and from
-                (let ((stop-pos 
-                       (string-match "  *at \\|  *@ \\| *(\\| *<" from)))
-                  (setq message-of
-                        (concat (if stop-pos (substring from 0 stop-pos) from)
-                                "'s message of " date))))
-           (setq subject (header-subject header))
-           (or (string-match "^[Rr][Ee]:" subject)
-               (setq subject (concat "Re: " subject)))
-           (setq followup-to (mail-fetch-field "followup-to"))
-           (if (or (null gnus-use-followup-to) ;Ignore followup-to: field.
-                   (string-equal "" followup-to) ;Bogus header.
-                   (string-equal "poster" followup-to)) ;Poster
-               (setq followup-to nil))
-           (setq newsgroups (or followup-to (mail-fetch-field "newsgroups")))
-           (setq references (header-references header))
-           (setq distribution (mail-fetch-field "distribution"))
-           ;; Remove bogus distribution.
-           (and (string= distribution "world")
-                (setq distribution nil))
-           (setq message-id (header-id header))
-           (widen))
-         (setq news-reply-yank-from from)
-         (setq news-reply-yank-message-id message-id)
-         ;; Prevent getting BCC or FCC fields inserted for both mail
-         ;; and news.  
-         (let ((mail-self-blind
-                (and (not gnus-mail-self-blind) mail-self-blind))
-               (mail-archive-file-name
-                (and (not gnus-author-copy) mail-archive-file-name)))
-           (news-setup 
-            ;; Suggested by Daniel Quinlan <quinlan@best.com>.
-            (if (eq gnus-auto-mail-to-author 'ask)
-                (and (y-or-n-p "Also send mail to author? ") from)
-              (and gnus-auto-mail-to-author from))
-            subject message-of newsgroups article-buffer))
-         ;; Fold long references line to follow RFC1036.
-         (mail-position-on-field "References")
-         (let ((begin (- (point) (length "References: ")))
-               (fill-column 79)
-               (fill-prefix "\t"))
-           (if references (insert references))
-           (if (and references message-id) (insert " "))
-           (if message-id (insert message-id))
-           ;; The region must end with a newline to fill the region
-           ;; without inserting extra newline.
-           (fill-region-as-paragraph begin (1+ (point))))
-         (if distribution
-             (progn
-               (mail-position-on-field "Distribution")
-               (insert distribution)))))
-      (current-buffer))))
+       (nntp-wait-for-response "^[23].*$"))))
+
+(defun nntp-request-post-buffer 
+  (post group subject header article-buffer info follow-to
+       respect-poster)
+  (if (assq 'to-address (nth 4 info))
+      (nnmail-request-post-buffer 
+       post group subject header article-buffer info follow-to respect-poster)
+    (let (from date to followup-to newsgroups message-of
+              references distribution message-id)
+      (save-excursion
+       (set-buffer (get-buffer-create "*post-news*"))
+       (news-reply-mode)
+       (if (and (buffer-modified-p)
+                (> (buffer-size) 0)
+                (not (y-or-n-p "Unsent article being composed; erase it? ")))
+           ()
+         (erase-buffer)
+         (if post
+             (news-setup nil subject nil group nil)
+           (save-excursion
+             (set-buffer article-buffer)
+             (goto-char (point-min))
+             (narrow-to-region (point-min)
+                               (progn (search-forward "\n\n") (point)))
+             (setq from (header-from header))
+             (setq date (header-date header))
+             (and from
+                  (let ((stop-pos 
+                         (string-match "  *at \\|  *@ \\| *(\\| *<" from)))
+                    (setq 
+                     message-of
+                     (concat (if stop-pos (substring from 0 stop-pos) from) 
+                             "'s message of " date))))
+             (setq subject (or subject (header-subject header)))
+             (or (string-match "^[Rr][Ee]:" subject)
+                 (setq subject (concat "Re: " subject)))
+             (setq followup-to (mail-fetch-field "followup-to"))
+             (if (or (null respect-poster) ;Ignore followup-to: field.
+                     (string-equal "" followup-to) ;Bogus header.
+                     (string-equal "poster" followup-to)) ;Poster
+                 (setq followup-to nil))
+             (setq newsgroups
+                   (or follow-to followup-to (mail-fetch-field "newsgroups")))
+             (setq references (header-references header))
+             (setq distribution (mail-fetch-field "distribution"))
+             ;; Remove bogus distribution.
+             (and (stringp distribution)
+                  (string-match "world" distribution)
+                  (setq distribution nil))
+             (setq message-id (header-id header))
+             (widen))
+           (setq news-reply-yank-from from)
+           (setq news-reply-yank-message-id message-id)
+           (news-setup to subject message-of newsgroups article-buffer)
+           ;; Fold long references line to follow RFC1036.
+           (mail-position-on-field "References")
+           (let ((begin (- (point) (length "References: ")))
+                 (fill-column 79)
+                 (fill-prefix "\t"))
+             (if references (insert references))
+             (if (and references message-id) (insert " "))
+             (if message-id (insert message-id))
+             ;; The region must end with a newline to fill the region
+             ;; without inserting extra newline.
+             (fill-region-as-paragraph begin (1+ (point))))
+           (if distribution
+               (progn
+                 (mail-position-on-field "Distribution")
+                 (insert distribution)))))
+       (current-buffer)))))
 
 ;;; Internal functions.
 
+(defun nntp-send-mode-reader ()
+  "Send the MODE READER command to the nntp server.
+This function is supposed to be called from `nntp-server-opened-hook'.
+It will make innd servers enter nnrpd mode to allow actual article
+reading."
+  (nntp-send-command "^.*\r$" "MODE READER"))
+
+(defun nntp-send-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 "^.*\r$" "AUTHINFO USER" (user-login-name))
+  (nntp-send-command "^.*\r$" "AUTHINFO PASS" (read-string "NNTP password: ")))
+
 (defun nntp-default-sentinel (proc status)
   "Default sentinel function for NNTP server process."
   (let ((servers nntp-server-alist))
+    ;; Go through the alist of server names and find the name of the
+    ;; server that the process that sent the signal is connected to.
+    ;; If you get my drift.
     (while (and servers 
                (not (equal proc (nth 1 (car servers)))))
       (setq servers (cdr servers)))
@@ -440,6 +451,14 @@ in the current news group."
             (or (car (car servers)) "(none)"))
     (ding)))
 
+(defun nntp-kill-connection (server)
+  (let ((proc (nth 1 (assoc server nntp-server-alist))))
+    (if proc (delete-process (process-name proc)))
+    (nntp-close-server server)
+    (setq nntp-status-string 
+         (message "Connection timed out to server %s." server))
+    (ding)))
+
 ;; Encoding and decoding of NNTP text.
 
 (defun nntp-decode-text ()
@@ -463,8 +482,7 @@ in the current news group."
       (end-of-line)
       (if (= (preceding-char) ?\r)
          (delete-char -1))
-      (forward-line 1)
-      )
+      (forward-line 1))
     ;; Delete `.' at end of buffer (end of text mark).
     (goto-char (point-max))
     (forward-line -1)                  ;(beginning-of-line)
@@ -474,8 +492,7 @@ in the current news group."
     (goto-char (point-min))
     ;; (replace-regexp "^\\.\\." ".")
     (while (search-forward "\n.." nil t)
-      (delete-char -1))
-    ))
+      (delete-char -1))))
 
 (defun nntp-encode-text ()
   "Encode text in current buffer for NNTP transmission.
@@ -493,8 +510,7 @@ in the current news group."
       (insert "."))
     ;; Insert `.' at end of buffer (end of text mark).
     (goto-char (point-max))
-    (insert ".\r\n")
-    ))
+    (insert ".\r\n")))
 
 \f
 ;;;
@@ -510,8 +526,7 @@ in the current news group."
     (apply 'nntp-send-strings-to-server cmd args)
     (if response
        (nntp-wait-for-response response)
-      t)
-    ))
+      t)))
 
 (defun nntp-wait-for-response (regexp)
   "Wait for server response which matches REGEXP."
@@ -538,8 +553,7 @@ in the current news group."
              ((looking-at "[45]")
               (setq status nil)
               (setq wait nil))
-             (t (nntp-accept-response))
-             ))
+             (t (nntp-accept-response))))
       ;; Save status message.
       (end-of-line)
       (setq nntp-status-string
@@ -562,16 +576,12 @@ in the current news group."
                            (setq dotnum newnum)
                            (message "NNTP: Reading %s"
                                     (make-string dotnum ?.))))))
-               (nntp-accept-response)
-               ;;(if nntp-debug-read (message ""))
-               ))
+               (nntp-accept-response)))
            ;; Remove "...".
            (if (and nntp-debug-read (> dotnum 0))
                (message ""))
            ;; Successfully received server response.
-           t
-           ))
-      )))
+           t)))))
 
 \f
 ;;;
@@ -620,8 +630,7 @@ in the current news group."
          (save-excursion
            (set-buffer nntp-server-buffer)
            (erase-buffer))))
-    (process-send-string nntp-server-process (concat cmd "\r\n"))
-    ))
+    (process-send-string nntp-server-process (concat cmd "\r\n"))))
 
 (defun nntp-send-region-to-server (begin end)
   "Send current buffer region (from BEGIN to END) to news server."
@@ -651,11 +660,9 @@ in the current news group."
          ;;  problem of communication error of GNU Emacs.
          (accept-process-output)
          ;;(sit-for 0)
-         (goto-char last)
-         )))
+         (goto-char last))))
     ;; We cannot erase buffer, because reply may be received.
-    (delete-region begin end)
-    ))
+    (delete-region begin end)))
 
 (defun nntp-open-server-internal (server &optional service)
   "Open connection to news server on SERVER by SERVICE (default is nntp)."
@@ -669,8 +676,8 @@ in the current news group."
       (set-buffer nntp-server-buffer)
       (if (setq proc
                (condition-case nil
-                   (open-network-stream "nntpd" (current-buffer)
-                                        server (or service "nntp"))
+                   (open-network-stream 
+                    "nntpd" (current-buffer) server (or service "nntp"))
                  (error nil)))
          (progn
            (setq nntp-server-process proc)
@@ -690,16 +697,9 @@ in the current news group."
   (if nntp-server-process
       (delete-process nntp-server-process))
   (setq nntp-server-process nil)
-  (let* ((servers nntp-server-alist)
-        (prev servers))
-    (if (and servers (string= (car (car servers)) server))
-       (setq nntp-server-alist (cdr nntp-server-alist))
-      (setq servers (cdr servers))
-      (while servers
-       (if (string= (car (car servers)) server)
-           (setcdr prev (cdr servers)))
-       (setq prev servers)
-       (setq servers (cdr servers))))))
+  (setq nntp-server-alist (delq (assoc nntp-current-server nntp-server-alist)
+                               nntp-server-alist))
+  (setq nntp-current-server ""))
 
 (defun nntp-request-close ()
   "Close all server connections."
@@ -717,26 +717,25 @@ defining this function as macro."
   ;;  accept-process-output is called.
   ;; Suggested by Jason Venner <jason@violet.berkeley.edu>.
   ;; This is a copy of `nntp-default-sentinel'.
-  (or (memq (process-status nntp-server-process) '(open run))
-      (error "NNTP: Connection closed."))
-  (if nntp-buggy-select
-      (progn
-       ;; We cannot use `accept-process-output'.
-       ;; Fujitsu UTS requires messages during sleep-for. I don't know why.
-       (message "NNTP: Reading...")
-       (sleep-for 1)
-       (message ""))
-    (condition-case errorcode
-       (accept-process-output nntp-server-process)
-      (error
-       (cond ((string-equal "select error: Invalid argument" (nth 1 errorcode))
-             ;; Ignore select error.
-             nil
-             )
-            (t
-             (signal (car errorcode) (cdr errorcode))
-       ))
-    ))))
+  (if (or (not nntp-server-process)
+         (not (memq (process-status nntp-server-process) '(open run))))
+      (error (format "nntp: Process connection closed"))
+    (if nntp-buggy-select
+       (progn
+         ;; We cannot use `accept-process-output'.
+         ;; Fujitsu UTS requires messages during sleep-for. I don't know why.
+         (message "NNTP: Reading...")
+         (sleep-for 1)
+         (message ""))
+      (condition-case errorcode
+         (accept-process-output nntp-server-process)
+       (error
+        (cond ((string-equal "select error: Invalid argument" 
+                             (nth 1 errorcode))
+               ;; Ignore select error.
+               nil)
+              (t
+               (signal (car errorcode) (cdr errorcode)))))))))
 
 (defun nntp-last-element (list)
   "Return last element of LIST."
@@ -765,11 +764,12 @@ defining this function as macro."
                (setq result t))))
       (setq result t))
     ;; The we see whether it is necessary to change newsgroup.
-    (if (and newsgroup result (or (not (string= newsgroup nntp-current-group))
-                                 changed-server))
-       (progn
-         (setq result (nntp-request-group newsgroup server))
-         (setq nntp-current-group newsgroup)))
+    (and newsgroup result 
+        (or (not (string= newsgroup nntp-current-group))
+            changed-server)
+        (progn
+          (setq result (nntp-request-group newsgroup server))
+          (setq nntp-current-group newsgroup)))
     result))
 
 (provide 'nntp)
index 27ce4d7..c7cd266 100644 (file)
@@ -1,7 +1,7 @@
 ;;;; nnvirtual.el --- virtual newsgroups access for (ding) Gnus
 ;; Copyright (C) 1994,95 Free Software Foundation, Inc.
 
-;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news
 
                (setq article (read nntp-server-buffer))
                (delete-region beg (point))
                (insert (int-to-string (+ (- article active) offset)))
-               (end-of-line)
-               (setq beg (point))
-               (search-backward "\t")
-               (if (not (search-forward "Xref:" beg t))
+               (beginning-of-line)
+               (looking-at "[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t")
+               (goto-char (match-end 0))
+               (or (search-forward 
+                    "\t" (save-excursion (end-of-line) (point)) t)
+                   (end-of-line))
+               (while (= (char-after (1- (point))) ? )
+                 (forward-char -1)
+                 (delete-char 1))
+               (if (eolp)
                    (progn
                      (end-of-line)
                      (or (= (char-after (1- (point))) ?\t)
                              (save-excursion (end-of-line) (point)) t)
                        (save-excursion
                          (goto-char (match-beginning 0))
-                         (insert prefix)))))
+                         (insert prefix))))
+                 (end-of-line)
+                 (or (= (char-after (1- (point))) ?\t)
+                     (insert ?\t)))
                (forward-line 1))))
        (goto-char (point-max))
        (insert-buffer-substring nntp-server-buffer))
@@ -135,7 +144,7 @@ If the stream is opened, return T, otherwise return NIL."
   (and nntp-server-buffer
        (get-buffer nntp-server-buffer)))
 
-(defun nnvirtual-status-message ()
+(defun nnvirtual-status-message (&optional server)
   "Return server status response as string."
   nnvirtual-status-string)
 
@@ -215,7 +224,9 @@ If the stream is opened, return T, otherwise return NIL."
                (or (header-references header) "") "\t"
                (int-to-string (or (header-chars header) 0)) "\t"
                (int-to-string (or (header-lines header) 0)) "\t"
-               (or (header-xref header) "") "\n")))))
+               (if (header-xref header) 
+                   (concat "Xref: " (header-xref header) "\t")
+                 "") "\n")))))
 
 (defun nnvirtual-possibly-change-newsgroups (group regexp &optional check)
   (let ((inf t))
@@ -273,31 +284,44 @@ If the stream is opened, return T, otherwise return NIL."
        ;; if not, we do it now.
        (if (null active)
            (if (gnus-activate-newsgroup igroup)
-               (gnus-get-unread-articles-in-group
-                info (gnus-gethash igroup gnus-active-hashtb))
-             (message "Couldn't request newsgroup %s" group)
+               (progn
+                 (gnus-get-unread-articles-in-group
+                  info (gnus-gethash igroup gnus-active-hashtb))
+                 (setq active (gnus-gethash igroup gnus-active-hashtb)))
+             (message "Couldn't open component group %s" igroup)
              (ding)))
-       (setq itotal (1+ (- (cdr active) (car active))))
-       (if (setq ireads (nth 2 info))
-           (let ((itreads
-                  (if (atom (car ireads)) 
-                      (setq ireads (list (cons (car ireads) (cdr ireads))))
-                    (setq ireads (copy-alist ireads)))))
-             (if (< (cdr (car ireads)) (car active))
-                 (setq ireads (setq itreads (cdr ireads))))
-             (if (< (car (car ireads)) (car active)) 
-                 (setcar (car ireads) (1+ (car active))))
-             (while itreads
-               (setcar (car itreads)
-                       (+ (- (car (car itreads)) (car active)) offset))
-               (setcdr (car itreads)
-                       (+ (- (cdr (car itreads)) (car active)) offset))
-               (setq itreads (cdr itreads)))
-             (setq reads (nconc reads ireads))))
-       (setq offset (+ offset (1- itotal)))
-       (setq nnvirtual-current-mapping
-             (cons (list offset igroup (car active)) 
-                   nnvirtual-current-mapping))
+       (if (null active)
+           ()
+         ;; And then we do the mapping for this component group. If
+         ;; you feel tempte to cast your eyes to the soup below -
+         ;; don't. It'll hurt your soul. Suffice to say that it
+         ;; assigns ranges of nnvirtual article numbers to the
+         ;; different component groups. To get the article number
+         ;; from the nnvirtual number, one does something like
+         ;; (+ (- number offset) (car active)), where `offset' is the
+         ;; slice the mess below assigns, and active is the lowest
+         ;; active article in the component group. 
+         (setq itotal (1+ (- (cdr active) (car active))))
+         (if (setq ireads (nth 2 info))
+             (let ((itreads
+                    (if (atom (car ireads)) 
+                        (setq ireads (list (cons (car ireads) (cdr ireads))))
+                      (setq ireads (copy-alist ireads)))))
+               (if (< (cdr (car ireads)) (car active))
+                   (setq ireads (setq itreads (cdr ireads))))
+               (if (and ireads (< (car (car ireads)) (car active)))
+                   (setcar (car ireads) (1+ (car active))))
+               (while itreads
+                 (setcar (car itreads)
+                         (+ (- (car (car itreads)) (car active)) offset))
+                 (setcdr (car itreads)
+                         (+ (- (cdr (car itreads)) (car active)) offset))
+                 (setq itreads (cdr itreads)))
+               (setq reads (nconc reads ireads))))
+         (setq offset (+ offset (1- itotal)))
+         (setq nnvirtual-current-mapping
+               (cons (list offset igroup (car active)) 
+                     nnvirtual-current-mapping)))
        (setq groups (cdr groups))))
     (setq nnvirtual-current-mapping
          (nreverse nnvirtual-current-mapping))
index 8c8c193..2417202 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo                  @c -*-texinfo-*-
 @comment %**start of header (This is for running Texinfo on a region.)
 @setfilename gnus
-@settitle (ding) Gnus 1.0 Manual
+@settitle (ding) Gnus 0.1 Manual
 @synindex fn cp
 @synindex vr cp
 @synindex pg cp
@@ -18,9 +18,9 @@
 
 @ifinfo
 
-This file documents GNUS, the GNU Emacs newsreader.
+This file documents (ding) Gnus, the GNU Emacs newsreader.
 
-Copyright (C) 1989, 1990, 1993 Free Software Foundation, Inc.
+Copyright (C) 1989, 1990, 1993, 1995 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -43,9 +43,9 @@ into another language, under the above conditions for modified versions.
 @end ifinfo
 
 @titlepage
-@title Gnus Manual
+@title (ding) Gnus Manual
 
-@author by Lars Ingebrigtsen
+@author by Lars Magne Ingebrigtsen
 @page
 @vskip 0pt plus 1filll
 Copyright @copyright{} 1989, 1990, 1993 Free Software Foundation, Inc. 
@@ -67,86 +67,131 @@ Cover art by Etienne Suvasa.
 @page
 
 @node Top
-@top The Gnus News Reader
+@top The Gnus Newsreader
 
-You can read news (and mail) from within Emacs by using (ding) Gnus.  The
-news can be gotten by any nefarious means you can think of - NNTP, local
-spool, mail spool.  All at the same time, if you want to push your luck.
-
-This manual documents (ding) Gnus 0.11. Gnus is now up to 0.29, so this
-documentation is totally out of date. The only authoratative
-documentation available is the source code.
+You can read news (and mail) from within Emacs by using (ding) Gnus.
+The news can be gotten by any nefarious means you can think of - NNTP,
+local spool or your mbox file.  All at the same time, if you want to
+push your luck.
 
 @menu
 * History::                 How Gnus got where it is today.
+* Terminology::             We use really difficult, like, words here.
 * Starting Up::             Finding news can be a pain.
-* The Group Buffer::        Treating groups.
-* The Summary Buffer::      Reading articles.
-* The Article Buffer::      Doing stuff to articles.
-* Various::                 General options.
+* The Group Buffer::        Selecting, subscribing and killing groups.
+* The Summary Buffer::      Reading, saving and posting articles.
+* The Article Buffer::      Displaying and handling articles.
+* Various::                 General purpose settings.
 * Customization::           Tailoring Gnus to your needs.
 * Troubleshooting::         What you might try if things do not work.
 * Reporting Bugs::          Bugs? What bugs?!
-* Index::                   Index.
+* Index::                   Variable, function and concept index.
 * Key Index::               Key Index.
 @end menu
 
-Note: This is a work of fiction. Any similarity between this manual and
+Note: This is a work of fiction.  Any similarity between this manual and
 real programs is purely coincidental.
 
 @node History
 @chapter History
 
-GNUS was written by Masanobu UMEDA.  When autumn crept up in '94, Lars
-Magne Ingebrigtsen grew bored and decided to write (ding) Gnus.
+@cindex history
+@sc{GNUS} was written by Masanobu UMEDA.  When autumn crept up in '94,
+Lars Magne Ingebrigtsen grew bored and decided to write (ding) Gnus.
 
-(ding) Gnus is based on GNUS 4.1 and includes bits and pieces by Per
-Abrahamsen, Sudish Joseph, Felix Lee and jwz. 
+(ding) Gnus is based on @sc{GNUS 4.1} and includes excellent functions
+from Per Abrahamsen, lots of fixes by Sudish Joseph, as well as bits and
+pieces from the XGnus distribution by Felix Lee and JWZ.
 
 The recommended pronounciation of the name this program is "ding
 guh-noose", with "ding" being half-sung in a loud, high-pitched voice,
-and "guh-noose" being grumbled and a disaffected fashion.  Any irritation
-and/or damage this name may cause you is not the responsibility of the
-author, even though you might like to strangle him for the stupid idea.
-
-"(ding)", is, of course, short for "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 UMEDA intended, which makes it a
-more appropriate name, don't you think?)
+and "guh-noose" being grumbled and a disaffected fashion.  Any
+irritation and/or damage this name may cause you is not the
+responsibility of the author, even though you might like to strangle him
+for the stupid idea.
+
+If you want to take a look at 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, also know as
+The Site That Destroys Newsrcs And Drives People Mad.
+
+@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 UMEDA intended,
+which makes it a more appropriate name, don't you think?)
 
 @menu
-* Compatibility::          Just how compatible is (ding) Gnus with GNUS?
+* Compatibility::          Just how compatible is (ding) Gnus with @sc{GNUS}?
 * New Features::           A short description of all the new stuff in Gnus.
 @end menu
 
 @node Compatibility
 @section Compatibility
 
-(ding) Gnus was designed to be fully compatible with GNUS.  Almost all
-key binding have been kept.  More key binding have been added, of course,
-but only in one or two obscure cases have key bindings been changed.
+@cindex compatability
+(ding) Gnus was designed to be fully compatible with @sc{GNUS}.  Almost
+all key binding have been kept.  More key binding have been added, of
+course, but only in one or two obscure cases have key bindings been
+changed.
+
+Our motto is:
+@quotation
+@cartouche
+In a cloud bones of steel.
+@end cartouche
+@end quotation
 
 All commands have kept their names.  Some internal functions have changed
 their names.
 
+The @code{gnus-uu} package has changed drastically. @xref{Decoding
+Articles}. 
+
+One major compatability question if the presence of several summary
+buffers.  The variables that are relevant while reading a group are
+buffer-local to the summary buffer they belong in.  Although most
+important variables have their values copied into their global
+counterparts whenever a command is executed in the summary buffer, this
+might lead to incorrect values being used if one is not careful.
+
+All code that relies on knowledge of @sc{GNUS} internals will probably
+fail.  To take two examples: Sorting @code{gnus-newsrc-assoc} (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 assoc (which
+speeds up many functions), and changing the assoc directly will lead to
+peculiar results.
+
+@cindex hilit19
+@cindex highlighting
+Old hilit19 code does not work at all.  In fact, you should probably
+remove all hihit code from all the Gnus hooks
+(@code{gnus-group-prepare-hook}, @code{gnus-summary-prepare-hook} and
+@code{gnus-summary-article-hook}).  (Well, at the very least the first
+two.)  Gnus provides various integrated functions for highlighting,
+which are both faster and more accurated. 
+
+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 (ding) Gnus.  More likely than not, (ding)
+Gnus already do what you have written code to make @sc{GNUS} do.
+(Snicker.)
+
 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.
 
-(ding) Gnus understands all GNUS startup files.
+(ding) Gnus understands all @sc{GNUS} startup files.
 
 @kindex M-x gnus-bug
-Overall, a casual user who hasn't written much code that depends on GNUS
-internals should suffer no problems.  If problems occur, please let me
-know (@kbd{M-x gnus-bug}).
-
-However, code that depends on the buffers looking a particular way will
-almost invaribaly fail.  For instance, the summary buffer no longer 
-displays article numbers by default.
+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 (@kbd{M-x gnus-bug}).
 
 @node New Features
 @section New Features
+@cindex new features
 
 The look of all buffers can be changed by setting format-like variables.
  
@@ -160,20 +205,63 @@ can go back and retrieve enough headers to build a complete thread.
 Killed groups can be displayed in the group buffer, and you can read
 them as well.
 
-Gnus can do partial updates of new articles - you do not have to
-retrieve the entire active file just to check for new articles in a few
-groups.
+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.
 
 Gnus implements a sliding scale of subscribedness to groups.
 
-The approach to killing has been changed. Instead of simply killing or
+The approach to killing has been changed.  Instead of simply killing or
 not, you can score articles for easier reading.
 
+@node Terminology
+@chapter Terminology
+
+@cindex terminology
+@table @samp
+@item news
+This is what you are supposed to use this thing for - reading news.
+News is generally fetched from a nearby 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.
+@item mail
+Everything that's delivered to you personally is mail.  Some news/mail
+readers (like Gnus) blur the distinction between mail and news, but
+there is a difference.  Mail is private.  News is public.  Mailing is
+not posting, and replying is not following up.
+@item reply
+Send a mail to the person who has written what you are reading.
+@item follow up
+Post an article to the current newsgroup responding to the article you
+are reading.
+@item 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 native
+Gnus will always use one method (and backend) as the @dfn{native}, or
+default, way of getting news.
+@item foreign
+You can also have any number of foreign groups at the same time.  These
+are groups that use different backends for getting news.
+@item header
+A line from the head of an article. 
+@item headers
+A collection of such lines, or a collection of heads.  Or even a
+collection of NOV lines.
+@item NOV
+When Gnus enters a group, it asks the backend for the headers for all
+the unread articles in the group.  Most servers support the News OverView
+format, which is much smaller and much faster to read than the normal
+HEAD format. 
+@end table
+
 @node Starting Up
 @chapter Starting Gnus
+@cindex starting up
 
 @kindex M-x gnus
-If your systems administrator has set thing up properly, starting Gnus
+If your system administrator has set thing up properly, starting Gnus
 and reading news is extremely easy - you just type @kbd{M-x gnus}.
 
 If things do not go smoothly at startup, you have to twiddle some
@@ -181,7 +269,7 @@ variables.
 
 @menu
 * Finding the News::    Choosing a method for getting news.
-* First Time::          What does Gnus do the first time you start it?
+* The First Time::      What does Gnus do the first time you start it?
 * The Server is Down::  How can I read my mail then?
 * New Groups::          What is Gnus supposed to do with new groups?
 * Startup Files::       Those pesky startup files - @file{.newsrc}.
@@ -196,138 +284,147 @@ variables.
 @vindex gnus-select-method
 The @code{gnus-select-method} variable controls how Gnus finds news.
 This variable should be a list where the first element says "how" and
-the second element says "where". This server is is your @dfn{local
-server}. All other servers are @dfn{foreign servers}.
+the second element says "where".  This method is is your native method.
+All groups that are not fetched with this method are foreign groups.
 
 For instance, if you want to get your daily dosage of news from the NNTP
 server "news.friendly.server", you'd say:
 
-@example
+@lisp
 (setq gnus-select-method '(nntp "news.friendly.server"))
-@end example
+@end lisp
 
 If you want to use a local spool, say:
 
-@example
+@lisp
 (setq gnus-select-method '(nnspool ""))
-@end example
+@end lisp
+
+If you can use the local spool, you probably should, as it will almost
+certainly be much faster.
 
 If this variable is not set, Gnus will take a look at the
 @code{NNTPSERVER} environment variable.  If that isn't set either, it
 will try to use the machine that is running Emacs as an NNTP server.
 
+@vindex gnus-nntp-server
+If @code{gnus-nntp-server} is set, this variable will override
+@code{gnus-select-method}.  You should therefore set
+@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 NNTP
-server.  If you give a non-numerical prefix to `gnus' (ie. `C-u M-x
-gnus'), Gnus will let you choose between the servers in the
-@code{gnus-secondary-servers} variable (if any).  You can also just type
-in the name of any server you feel like visiting.
+server.  If you give a non-numerical prefix to @code{gnus} (ie. @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.
 
 However, if you use one NNTP server regularly, and is just interested in
-a couple of groups from a different server, you would be better
-served by using the @code{gnus-group-browse-foreign-server} command from
-the group buffer.  It will let you have a look at what groups are
-available, and you can subscribe to any of the groups you want to.  This
-also makes @file{.newsrc} maintenance much tidier.
+a couple of groups from a different server, you would be better served
+by using the @code{gnus-group-browse-foreign-server} command from the
+group buffer.  It will let you have a look at what groups are available,
+and you can subscribe to any of the groups you want to.  This also makes
+@file{.newsrc} maintenance much tidier.  @xref{Foreign Groups}.
 
 @vindex gnus-secondary-select-methods
-A slightly different approach is to set the
-@code{gnus-secondary-select-methods}. The select methods listed in this
-variable are in many ways just as local as the @code{gnus-select-method}
-server. They will also be asked for active files during startup (if
-that's wanted), and new newsgroups that appear from these servers will
-be subscribed (or not) just as local groups are.
+A slightly different approach to foreign groups is to set the
+@code{gnus-secondary-select-methods} variable.  The select methods
+listed in this variable are in many ways just as native as the
+@code{gnus-select-method} server.  They will also be asked for active
+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 you mail, you
 would typically set this variable to
 
-@example
+@lisp
 (setq gnus-secondary-select-methods 
   '((nnmbox "")))
-@end example
+@end lisp
 
-@node First Time
+@node The First Time
 @section The First Time
+@cindex first time usage
 
-One time has to be the first, but it doesn't have to be painful.
-
-If no startup files exist, Gnus will try to determine what groups
-that should be subscribed by default.
+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
-will subscribe you to just those groups in that list, leaving the
-rest killed.  Your systems administrator should have set this variable to
+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 randomly picked
-groups (ie. @samp{*.newusers}). (@dfn{Random} is here defined as
-"whatever Lars think you should read".)
+groups (ie. @samp{*.newusers}).  (@dfn{Random} is here defined as
+"whatever Lars thinks you should read".)
 
-If @code{gnus-default-subscribed-newsgroups} is t, Gnus will just use
-the normal functions for treating new groups, and not do anything
+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 use
+the normal functions for handling new groups, and not do anything
 special.
 
 @node The Server is Down
 @section The Server is Down
+@cindex server errors
 
 If the default server is down, Gnus will understandably have some
-problems starting. However, if you have some mail groups in addition to
+problems starting.  However, if you have some mail groups in addition to
 the news groups, you may want to start Gnus anyway.
 
-You can bo that by @kbd{M-x gnus-no-server}. This will start Gnus
-without attempting to contact the default server. Gnus will be started
-on level two, so you shouldn't have any groups from the local server on
+@findex gnus-no-server
+You can do that by @kbd{M-x gnus-no-server}.  This will start Gnus
+without attempting to contact the default server.  Gnus will be started
+on level two, so you shouldn't have any groups from the native server on
 level one or two, but only have mail groups and other foreign groups on
 these two levels.
 
 @node New Groups
 @section New Groups
+@cindex new groups
 
 @vindex gnus-subscribe-newsgroup-method
 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.  Some handy ready-made values
+This variable should contain a function.  Some handy pre-fab values
 are:
 
 @table @code
 @item gnus-subscribe-randomly
 @vindex gnus-subscribe-randomly
 Subscribe all new groups randomly.
-
 @item gnus-subscribe-alphabetically
 @vindex gnus-subscribe-alphabetically
 Subscribe all new groups alphabetically.
-
 @item gnus-subscribe-hierarchically
 @vindex gnus-subscribe-hierarchically
 Subscribe all new groups hierarchially.
-
 @item gnus-subscribe-interactively
 @vindex gnus-subscribe-interactively
 Subscribe new groups interactively.  This means that Gnus will ask
-you about *all* new groups.
-
+you about @strong{all} new groups.
 @item gnus-subscribe-zombies
 @vindex gnus-subscribe-zombies
 Make all new groups zombies.  You can browse the zombies later and
-either kill them off properly or subscribe to them.  This is the
-default. 
-
+either kill them all off properly, or subscribe to them.  This is the
+default.
 @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-nil, Gnus will ask you in a
+@code{gnus-subscribe-hierarchical-interactive}.  (That's quite a
+mouthful.)  If this variable is non-@code{nil}, Gnus will ask you in a
 hierarchial 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.
 
 One common way to control which new newsgroups should be subscribed or
 ignored is to put an @dfn{options} line at the start of the
-@file{.newsrc} file. Here's an example:
+@file{.newsrc} file.  Here's an example:
 
 @example
 options -n !alt.all !rec.all sci.all
@@ -338,60 +435,82 @@ This line obviously belongs to a serious-minded intellectual scientific
 person (or she may just be plain old boring), because it says that all
 groups that have names beginning with @samp{alt} and @samp{rec} should
 be ignored, and all groups with names beginning with @samp{sci} should
-be subscribed. Gnus doesn't use the normal subscription method for
-subscribing these groups. @code{gnus-subscribe-options-newsgroup-method}
-is used instead. This variable defaults to
-@code{gnus-subscribe-alphabetically}. 
+be subscribed.  Gnus will not use the normal subscription method for
+subscribing these groups.
+@code{gnus-subscribe-options-newsgroup-method} is used instead.  This
+variable defaults to @code{gnus-subscribe-alphabetically}.
+
+@vindex gnus-options-not-subscribe
+@vindex gnus-options-subscribe
+If you don't want to mess with your @file{.newsrc} file, you can just
+set the two variables @code{gnus-options-subscribe} and
+@code{gnus-options-not-subscribe}.  These two variables do exactly the
+same as the @file{.newsrc} options -n trick.  Both are regexps, and if
+the the new group matches the first, it will be unconditionally
+subscribed, and if it matches the latter, it will be ignored.
 
 @vindex gnus-check-new-newsgroups
-If you are satisfied that you never really want to see any new
-groups, you could set @code{gnus-check-new-newsgroups} to
-nil.  This will also save you some time at startup.  Even if this
-variable is nil, you can always subscribe to the new groups
-by just pressing @kbd{U} in the @dfn{group buffer}.
-
-If @code{gnus-check-new-newsgroups} is @code{ask-server}, Gnus will ask
-the server for new groups since last time it asked instead of
-determining what groups are new by comparing active groups with known
-groups. This is both faster & 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 nil, which will save time both at
-startup, at exit, and all over. Saves disk space, too. The only problem
-with this method is that not all servers support this functionality.
+If you are satisfied that you really never want to see any new groups,
+you could set @code{gnus-check-new-newsgroups} to @code{nil}.  This will
+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}).
+
+Gnus normally determine 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
+server for new groups since the last time.  This is both faster &
+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 function.
+
+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
+that startup will take much longer, so you can meditate while waiting.
+Use the mantra "dingnusdingnusdingnus" to achieve permanent happiness.
 
 @node Startup Files
 @section Startup Files
+@cindex startup files
+@cindex .newsrc
 
 Now, you all know about the @file{.newsrc} files.  All information about
-what groups you read is traditionally stored in this file, which has
-rather rigid structure.
+what groups you read is traditionally stored in this file, which has a
+rather rigid structure.
 
-Things got a bit more complicated with GNUS.  In addition to keeping the
-@file{.newsrc} file updated, it also used a file called @file{.newsrc.el} for
-storing all the information that didn't fit into the @file{.newsrc}
-file.  (Actually, it duplicated everything in the @file{.newsrc} file.)
-GNUS would read whichever one of these files that were the most recently
-saved, which enabled people to swap between GNUS and other newsreaders.
+Things got a bit more complicated with @sc{GNUS}.  In addition to
+keeping the @file{.newsrc} file updated, it also used a file called
+@file{.newsrc.el} for storing all the information that didn't fit into
+the @file{.newsrc} file.  (Actually, it duplicated everything in the
+@file{.newsrc} file.)  @sc{GNUS} would read whichever one of these files
+that were the most recently saved, which enabled people to swap between
+@sc{GNUS} and other newsreaders.
 
 That was kinda silly, so (ding) Gnus went one better: In addition to the
 @file{.newsrc} and @file{.newsrc.el} files, (ding) Gnus also has a file
 called @file{.newsrc.eld}.  It will read whichever of these files that
-are most recent, but it will never write a @file{.newsrc.el} file. 
+are most recent, but it will never write a @file{.newsrc.el} file.
 
 @vindex gnus-save-newsrc-file
 You can also turn off writing @file{.newsrc} by setting
-@code{gnus-save-newsrc-file} to nil, which means you can delete
-the file and save some space, as well as some time when quitting
-Gnus.  However, that will make it impossible to use other newsreaders
-than (ding) Gnus.  But hey, who would want to, right? 
+@code{gnus-save-newsrc-file} to @code{nil}, which means you can delete
+the file and save some space, as well as some time when quitting Gnus.
+However, that will make it impossible to use other newsreaders than
+(ding) Gnus.  But hey, who would want to, right?
 
 @vindex gnus-save-killed-list
-If @code{gnus-save-killed-list} is nil, Gnus will not save the list of
-killed groups to the startup file.  This will save both time (when
-starting and quitting) and space (on disk).  It will also means that
-Gnus has no record of what groups are new or old, so the automatic new
-groups subscription methods become meaningless.  You should always set
-@code{gnus-check-new-newsgroups} to nil if you set this variable to nil.
+If @code{gnus-save-killed-list} is @code{nil}, Gnus will not save the
+list of killed groups to the startup file.  This will save both time
+(when starting and quitting) and space (on disk).  It will also means
+that Gnus has no record of what groups are new or old, so the automatic
+new groups subscription methods become meaningless.  You should always
+set @code{gnus-check-new-newsgroups} to @code{nil} if you set this
+variable to @code{nil}.
 
 @vindex gnus-startup-file
 The @code{gnus-startup-file} variable says where the startup files are.
@@ -400,44 +519,65 @@ startup file being whatever that one is with a @samp{".eld"} appended.
 
 @vindex gnus-save-newsrc-hook
 @code{gnus-save-newsrc-hook} is called before saving the @file{.newsrc}
-file. 
+file.
 
 @node Auto Save
 @section Auto Save
+@cindex dribble file
+@cindex auto-save
 
 Whenever you do something that changes the Gnus data (reading articles,
 cathing up, killing/subscribing to groups,) the change is added to a
 special @dfn{dribble} buffer.  This buffer is auto-saved the normal
-Emacs way.
+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
 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
+maintain a dribble buffer.
+
 @node The Active File
 @section The Active File
+@cindex active file
+@cindex ignored groups
 
-When Gnus starts, or indeed whenever it tries to determine if new
-articles has arrived, it reads the active file.  This is a file stored
-on the NNTP server or in the local spool.
+When Gnus starts, or indeed whenever it tries to determine whether new
+articles have arrived, it reads the active file.  This is a large file
+that the NNTP server maintains to keep track of what groups it carries.
 
 @vindex gnus-ignored-newsgroups
 Before examining the active file to see what groups are available, Gnus
-deletes all lines in this file that match
-@code{gnus-ignored-newsgroups}.  You may even use this variable to make
-Gnus ignore hierarchies you aren't interested in.
+deletes all lines in this file that match the regexp
+@code{gnus-ignored-newsgroups}.  This is done primarily to reject any
+groups with bogus names (eg. groups containing characters like
+@samp{'[]"} and so on), but you can use this variable to make Gnus
+ignore hierarchies you aren't ever interested in.
 
 @vindex gnus-read-active-file
 The active file can be rather Huge, so if you have a slow network, you
-can set @code{gnus-read-active-file} to nil to prevent Gnus from reading
-the entire active file.
+can set @code{gnus-read-active-file} to @code{nil} to prevent Gnus from
+reading the active file.
 
 Gnus will try to make do by just getting information on the groups
 that you actually subscribe to.
 
 Note that if you subscribe to lots and lots of groups, setting this
-variable to nil will probabaly make Gnus slower, not faster.
+variable to @code{nil} will probabaly 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.  Gnus does
+the group info fetching in total lock-step, so if you have this variable
+@code{nil}, you should kill all groups that you aren't interested in to
+speed things up.
+
+There are plans for doing lots of Gnus stuff asynchronously, which
+should make this option more useful, but that's probably some ways off
+in the future.
 
 @node Startup Variables
 @section Startup Variables
@@ -445,24 +585,26 @@ variable to nil will probabaly make Gnus slower, not faster.
 @table @code
 @item gnus-check-bogus-newsgroups
 @vindex gnus-check-bogus-newsgroups
-If non-nil, Gnus will check for and delete all bogus groups at
-startup.  A @dfn{bogus group} is a group that you have in you
+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 isn't very quick, so to save time and resources, it's
-best to leave this option off, and instead do the checking for bogus
-groups once in a while from the group buffer.
+bogus groups isn't very quick, so to save time and resources, it's best
+to leave this option off, and instead do the checking for bogus groups
+once in a while from the group buffer (@pxref{Group Maintenance}).
 @item gnus-inhibit-startup-message
 @vindex gnus-inhibit-startup-message
-If non-nil, the startup message won't be displayed.  That way, nobody will
-notice thay you are reading news instead of doing your job.
+If non-@code{nil}, the startup message won't be displayed.  That way,
+your boss might not notice thay you are reading news instead of doing
+your job.
 @end table
 
 @node The Group Buffer
 @chapter The Group Buffer
+@cindex group buffer
 
-The @dfn{group buffer} lists all (or parts) of the available
-groups and displays various information regarding these groups. 
-It is the first buffer displayed when Gnus starts.
+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.
 
 @menu
 * Group Buffer Format::    Information listed and how you can change it.
@@ -471,7 +613,7 @@ It is the first buffer displayed when Gnus starts.
 * Group Subscribing::      Unsubscribing, killing, subscribing.
 * Group Levels::           Levels? What are those, then?
 * Foreign Groups::         How to create foreign groups.
-* Listing Groups::         Gnus can list various classes of groups.
+* Listing Groups::         Gnus can list various subsets of the groups.
 * Group Maintenance::      Maintaining a tidy @file{.newsrc} file.
 * Browse Foreign Server::  You can browse a server.  See what if has to offer.
 * Exiting Gnus::           Stop reading news and get some work done.
@@ -480,6 +622,7 @@ It is the first buffer displayed when Gnus starts.
 
 @node Group Buffer Format
 @section Group Buffer Format
+@cindex group buffer format
 
 The default format of the group buffer is nice and dull, but you can
 make it as exciting and ugly as you feel like.
@@ -504,15 +647,23 @@ You can fuck that up to your heart's delight by fiddling with 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.
 
-One extension is that specifications like @samp{%7,12s} is allowed,
-which means that the field will be at least 7 characters long, and no
-more that 12 characters long.
+In addition to the normal "padding" specs that @code{format} supports
+(eg. @samp{%7d}), specifications like @samp{%7,12s} are allowed.  A spec
+of this type means that the field will be at least 7 characters long,
+and never more that 12 characters long.
 
 The default value that produced those lines above is 
-@samp{"%M%S%5y: %g\n"}.
+@samp{"%M%S%5y: %(%g%)\n"}.
+
+There should always be a colon on the line; the cursor always move 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.
 
-There should always be a colon on the line; the cursor is always moved
-to the colon.  Nothing else is required - not even the group name. 
+(Note that if you make a really strange, wonderful, spreadsheat-like
+layout, everybody will believe you are hard at work with the accounting
+instead of wasting time reading news.)
 
 Here's a list of all available format characters:
 
@@ -554,11 +705,19 @@ Select from where
 @item z
 A string that look like @samp{<%s:%n>} if a foreign select method is
 used. 
+@item u
+User defined specifier.  The next character in the format string should
+be a letter.  @sc{GNUS} will call the function gnus-user-format-function-X,
+where X is the letter following %u.  The function will be passed the
+current headers as argument.  The function should return a string, which
+will be inserted into the buffer just like information from any other
+specifier.
 @end table
 
 @vindex gnus-group-mode-line-format
-The mode line can also be changed (@code{gnus-group-mode-line-format}).
-It does not understand that many format specifiers:
+The mode line can be changed by setting
+(@code{gnus-group-mode-line-format}).  It doesn't understand that many
+format specifiers:
 
 @table @samp
 @item S
@@ -569,6 +728,7 @@ Default select method
 
 @node Group Manouvering
 @section Group Manouvering
+@cindex group movement
 
 All movement commands understand the numeric prefix and will behave as
 expected, hopefully. 
@@ -579,7 +739,8 @@ expected, hopefully.
 @findex gnus-group-next-unread-group
 Go to the next group with unread articles
 (@code{gnus-group-next-unread-group}). 
-@item p, DEL
+@item p
+@item DEL
 @kindex DEL (Group)
 @kindex p (Group)
 @findex gnus-group-prev-unread-group
@@ -603,15 +764,27 @@ Go to the next unread group on the same level (or lower)
 @findex gnus-group-prev-unread-group-same-level
 Go to the previous unread group on the same level (or lower)
 (@code{gnus-group-prev-unread-group-same-level}). 
+@end table
+
+Two commands for jumping to groups:
+
+@table @kbd
 @item j
 @kindex j (Group)
 @findex gnus-group-jump-to-group
 Jump to a group (and make it visible if it isn't already)
-(@code{gnus-group-jump-to-group}). 
+(@code{gnus-group-jump-to-group}).  Killed groups can be jumped to, just
+like living groups.
+@item ,
+@kindex , (Group)
+@findex gnus-group-best-unread-group
+Jump to the unread group with the lowest level
+(@code{gnus-group-best-unread-group}). 
 @end table
 
 @node Selecting a Group
 @section Selecting a Group
+@cindex group selection
 
 @table @kbd
 @item SPACE
@@ -627,7 +800,8 @@ server.
 @kindex RET (Group)
 @findex gnus-group-select-group
 Select the current group and switch to the summary buffer
-(@code{gnus-group-select-group}). 
+(@code{gnus-group-select-group}).  If you give a prefix to this command,
+Gnus will fetch all available articles in this group.
 @item c
 @kindex c (Group)
 @findex gnus-group-catchup-current
@@ -641,25 +815,60 @@ Mark all articles in this group, even the ticked ones, as read
 @end table
 
 @vindex gnus-large-newsgroup
-The @code{gnus-large-newsgroup} variable says what Gnus considers to be
-a "big" group.  If the group is big, 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
-(@samp{-n}), the @samp{n} oldest articles will be fetched.  If it is
-positive, the @samp{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 the group has more unread articles than this
+variable, 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 (@samp{-n}), the @samp{n} oldest
+articles will be fetched.  If it is positive, the @samp{n} articles that
+have arrived most recently will be fetched.
+
+@vindex gnus-select-group-hook
 @vindex gnus-auto-select-newsgroup
-If @code{gnus-auto-select-newsgroup} is non-nil, the first unread
+If @code{gnus-auto-select-newsgroup} is non-@code{nil}, the first unread
 article in the group will be displayed when you enter the group.  If you
 want to prevent automatic selection in some group (say, in a binary
-group with Huge articles) you can set this variable to nil in
-`gnus-select-group-hook', which is called when a group is selected.
-This hook is also popularly used for sorting headers before generating
-the summary buffer.
+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 selected.
+
+@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
+@vindex gnus-thread-sort-functions
+If you are using threaded summary display, you can sort the threads by
+setting @code{gnus-thread-sort-functions}, which is a list of functions.
+By default, sorting is done on article numbers.  Ready-made sorting
+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},
+@code{gnus-thread-sort-by-total-score}. 
+
+Each function takes two threads and return non-@code{nil} if the first
+thread should be sorted before the other.  If you use more than one
+function, the primary sort key should be the last function in the list.
+
+If you would like to sort by score, then by subject, and finally by
+date, you could do something like:
+
+@lisp
+(setq gnus-thread-sort-functions 
+      '(gnus-thread-sort-by-date
+        gnus-thread-sort-by-subject
+        gnus-thread-sort-by-score))
+@end lisp
+
+@vindex gnus-thread-score-function
+The function in the @code{gnus-thread-score-function} variable (default
+@code{+}) is used for calculating the total score of a thread.  Useful
+functions might be @code{max}, @code{min}, or squared means, or whatever
+tickles you fancy.
 
 @node Group Subscribing
 @section Group Subscribing
+@cindex subscribing
 
 @table @kbd
 @item u
@@ -693,12 +902,13 @@ Kill all zombie groups (@code{gnus-group-kill-all-zombies}).
 
 @node Group Levels
 @section Group Levels
+@cindex group level
 
-All groups have a level of "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 and
-lower, or to just check new articles in groups on a given level and
-lower, etc. 
+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 and lower
+(@pxref{Listing Groups}), or to just check for new articles in groups on
+a given level and lower (@pxref{Misc Group Stuff}).
 
 @table @kbd
 @item S
@@ -706,21 +916,24 @@ lower, etc.
 @findex gnus-group-set-current-level
 Set the level of the current group depending on the numeric
 prefix.  For instance, @kbd{3 s} will set the level of the current
-group to three (@code{gnus-group-set-current-level}).
+group to three (@code{gnus-group-set-current-level}).  If no numeric
+prefix is given, this command will prompt the user for a level.
 @end table
 
 Gnus considers groups on levels 1-5 to be subscribed, 6-7 to be
 unsubscribed, 8 to be zombies (walking dead) and 9 to be killed,
 completely dead.  Gnus treats subscribed and unsubscribed groups exactly
 the same, but zombie and killed groups have no information on what
-articles you have read, etc, stored.
+articles you have read, etc, stored.  This distinction between dead and
+living groups isn't done because it is nice or clever, it is done purely
+for reasons of efficiency. 
 
-It is recommended that you keep all your "ordinary" groups on level 3 or
-higher, and keep your mail groups (if any) on level 1 or 2.
+It is recommended that you keep all regular groups on level 3 or higher,
+and keep your mail groups (if any) on level 1 or 2.
 
 @vindex gnus-keep-same-level
-If @code{gnus-keep-same-level} is non-nil, some movement commands will
-only move to groups that are of the same level (or lower).  In
+If @code{gnus-keep-same-level} is non-@code{nil}, some movement commands
+will only move to groups that are of the same level (or lower).  In
 particular, going from the last article in one group to the next group
 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
@@ -728,23 +941,58 @@ rest.
 
 @node Foreign Groups
 @section Foreign Groups
+@cindex foreign groups
 
 A @dfn{foreign group} is a group that is not read by the usual (or
 default) means.  It could be, for instance, a group from a different
-NNTP server, it could be a virtual group or it could be your own
+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 (eg. nntp,
+nnspool, nnml) and the second element is the "address", in some meaning of
+the word.  There may be additional elements in the select method, where
+the value may have special meaning for the backends.
+
+The @dfn{name} of the group is the name the backend will recognize the
+group as.
+
+For instance, the group @samp{soc.motss} on the NNTP server
+@samp{some.where.edu} will have the name @samp{soc.motss} and select
+method @samp{(nntp "some.where.edu")}.  Gnus will call this group, in
+all circumstances @samp{nntp+some.where.edu:soc.motss}, even though the
+nntp backend just knows this group as @samp{soc.motss}.
+
+Here are some commands for making and editing general foreign groups,
+and some commands to ease the creation of some special-purpose groups:
+
 @table @kbd
-@item M-a
-@kindex M-a (Group)
-@findex gnus-group-add-group
-Add a new group.  Gnus will prompt you for a name, a method and an
-"address" (@code{gnus-group-add-group}).
-@item M-e
-@kindex M-e (Group)
+@item M m
+@kindex M m (Group)
+@findex gnus-group-make-group
+Make a new group.  Gnus will prompt you for a name, a method and an
+"address" (@code{gnus-group-make-group}).
+@item M e
+@kindex M e (Group)
 @findex gnus-group-edit-group
 Edit a group entry.  Gnus will pop up a new buffer where you can edit
 the entry (@code{gnus-group-edit-group}).
+@item M d
+@kindex M d (Group)
+@findex gnus-group-make-directory-group
+Make a directory group.  You will be prompted for a directory name
+(@code{gnus-group-make-directory-group}).  
+@item M h 
+@kindex M h (Group)
+@findex gnus-group-make-help-group
+Make the (ding) Gnus help group (@code{gnus-group-make-help-group}).
+@item M k
+@kindex M k (Group)
+@findex gnus-group-make-kiboze-group
+Make a kiboze group.  You will be prompted for a name, for a regexp to
+match groups to be "included" in the kiboze group, and a series of
+strings to match on headers (@code{gnus-group-make-kiboze-group}).
 @end table
 
 The different methods all have their peculiarities, of course.
@@ -753,7 +1001,10 @@ The different methods all have their peculiarities, of course.
 * nntp::           Reading news from a different NNTP server.
 * nnspool::        Reading news from the local spool.
 * nnvirtual::      Combining articles from many groups.
-* nndir::          You can read a directory as if it were a newsgroup.
+* nnkiboze::       Looking through parts of the newsfeed for articles.
+* nndir::          You can read a directory as if it was a newsgroup.
+* nndoc::          Single files can be the basis of a group.
+* nndigest::       Digests can be undigested and treated as a group.
 * Mail::           Reading your personal mail with Gnus.
 @end menu
 
@@ -761,33 +1012,144 @@ The different methods all have their peculiarities, of course.
 If the @code{gnus-activate-foreign-newsgroups} is a positive number,
 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 NNTP servers.  It is nil by default, which means
-that you won't be told whether there are new articles in these groups.
-How many unread articles there are will be determined when, or if, you
-decide to enter them.
+groups from different NNTP servers.  It is @code{nil} by default, which
+means that you won't be told whether there are new articles in these
+groups.  How many unread articles there are will be determined when, or
+if, you decide to enter them.  You can also activate any group with
+@kbd{M-g} to see how many unread articles there are.
+
+@cindex to-address
+If the select method contains an element that looks like
+@samp{(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 mailing lists.  You'd then just set this
+address to whatever the list address is.
+
+This trick 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 group, 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 achieve this, go to the group in question in the group buffer and
+type @kbd{M e} to edit the group entry.  You'll then be put in a buffer
+where you can edit the group entry.
+
+@lisp
+(gnus-group-set-info
+ '("ifi.fritt-forum" 3
+   ((1 . 3321)
+    (3325 . 3325))
+   ((score
+     (3322 . 1000)
+     (3324 . 1000)))))
+@end lisp
+
+A fifth entry has to be added. (In case there isn't a fourth one, you
+have to add a fourth one yourself - @code{nil}.)  The fifth entry should
+look like this:
+
+@lisp
+(nntp "your.host" (to-address . "4ad-l@@jhuvm.hcf.jhu.edu"))
+@end lisp
+
+The two first entries in this method should, of course, be the same as
+@code{gnus-select-method}. 
+
+Quite simple, eh? <duck> *Ouch*.
+
+Let's take time out for a poem by Reznikoff:
+
+@quotation
+Te Deum
+@sp 2
+Not because of victories @*
+I sing,@*
+having none,@*
+but for the common sunshine,@*
+the breeze,@*
+the largess of the spring.
+@sp 2
+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
 
 @node nntp
 @subsection nntp
+@cindex nntp
 
 Subscribing to a foreign group from an NNTP server is rather easy.  You
 just specify @code{nntp} as method and the address of the NNTP server as
 the, uhm, address.
 
+If the NNTP server is located at a non-standard port number, 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}).
+
 The name of the foreign group can be the same as a native group.  In
 fact, you can subscribe to the same group from as many different servers
-you feel like. There will be no name collisions.
+you feel like.  There will be no name collisions.
+
+@vindex nntp-server-opened-hook
+@code{nntp-server-opened-hook} is run after a connection has been made.
+It can be used to send initial commands to the NNTP server, like
+@samp{(nntp-send-command "MODE" "READER")} (which is what this hook does
+by default) or to send the @code{AUTHINFO} command, if the server
+requires that.
+
+@vindex nntp-maximum-request
+If the NNTP server doesn't support NOV headers, this backend will
+collect headers by sending a series of @code{HEAD} commands.  To speed
+things up, the backend 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.
+
+@vindex nntp-connection-timeout
+If you have lots of foreign nntp groups that you connect to regularly,
+you're sure to have problems with 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 nntp backend should wait for a connection before giving up.
+If it is @code{nil}, which is the default, no timeouts are done.
 
 @node nnspool
 @subsection nnspool
+@cindex nnspool
+@cindex news spool
 
 Subscribing to a foreign group from the local spool is extremely easy,
-and might be useful, for instance, to speed up reading binaries groups. 
+and might be useful, for instance, to speed up reading groups like
+@samp{alt.binaries.pictures.furniture}.
 
-Anyways, you just specify @code{nnspool} as the method and @samp{""} as
-the address.
+Anyways, you just specify @code{nnspool} as the method and @samp{""} (or
+anything else) as the address.
+
+If you have access to a local spool, you should probably use that as the
+native select method (@pxref{Finding the News}).
+
+@table @code
+@item nnspool-inews-program
+Program used to post an article.
+@item nnspool-spool-directory
+Where nnspool looks for the articles.  This is normally
+@file{/usr/spool/news/}.
+@item nnspool-nov-directory 
+Where nnspool will look for NOV files.  This is normally 
+@file{/usr/spool/news/over.view/}.
+@item nnspool-lib-dir
+Where the news lib dir is (@file{/usr/lib/news/} by default).
+@end table
 
 @node nnvirtual
 @subsection nnvirtual
+@cindex nnvirtual
+@cindex virtual groups
 
 A @dfn{virtual group} is really nothing more than a collection of
 other groups. 
@@ -799,51 +1161,158 @@ For instance, if you are tired of reading many small group, you can
 put them all in one big group, and then grow tired of reading one
 big, unwieldy group.  The joys of computing!
 
+All marks, read status, etc., in the nnvirtual group will stick to the
+articles in the component groups.  So if you tick an article in an
+nnvirtual group, the article will also be ticked in the component group
+from whence it it.  (And vice versa - marks from the component groups
+will also be shown in the nnvirtual group.)
+
 @example
-"^alt\\.fan\\.andrea-dworkin$\\|rec\\.dworkin.*"
+"^alt\\.fan\\.andrea-dworkin$\\|^rec\\.dworkin.*"
 @end example
 
 These groups can be native or foreign; everything should work smoothly,
-but if your computer explodes, it was probably my fault.  (Including
-other virtual groups in this one will probably confuse Gnus, so don't do
-that.)
+but if your computer explodes, it was probably my fault.  
+
+Collecting the same group from several servers might actually be a good
+idea if users have set the Distribution headers 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
+"^nntp+some.server.jp:soc.motss\\|^nntp+some.server.no:soc.motss"
+@end example
+
+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.
 
 One limitation, however - all groups that are included in a virtual
-group has to be alive (ie. subscribed or unsubscribed).  In fact, if you
-include a group in a virtual group, and it was killed, it will be
-subscribed automagically.
+group has to be alive (ie. subscribed or unsubscribed).  Killed or
+zombie groups can't be component groups for nnvirtual groups.
+
+@node nnkiboze
+@subsection nnkiboze
+@cindex nnkiboze
+@cindex kibozing
+
+@dfn{kibozing} is defined by OED as "grepping through (parts of) the
+news feed".  nnkiboze is a backend that will do this for you.  Oh joy!
+Now you can grind any NNTP server down to a halt with useless requests!
+Oh happiness!
+
+The address field of the nnkiboze method is, as with nnvirtual, a regexp
+to match groups to be "included" in the nnkiboze group.  There most
+similarities between nnkiboze and nnvirtual ends.
+
+In addition to this regexp detailing component groups, an nnkiboze group
+must have a score file to say what articles that are to be included in
+the group.
+
+@kindex M-x nnkiboze-generate-groups
+@findex nnkiboze-generate-groups
+After creating the nnkiboze groups you feel like having, you must run
+@kbd{M-x nnkiboze-generate-groups}.  (This can also be reached from one
+of the menus.) This will take time.  Lots of time.  Oodles ond oodles of
+time.  Gnus has to fetch the headers from all the articles on all the
+components 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
+nnkiboze groups.
+
+Please limit the number of component groups by using restrictive
+regexps.  Or your sysadm may become annoyed with you, and the NNTP site
+may throw you off and never let you back in again.  Stranger things have
+happened.
+
+nnkiboze component groups do not have to be alive - they can be dead,
+and they can be foreign.  No restrictions.
+
+@vindex nnkiboze-directory
+The generation of an nnkiboze group means writing two files in
+@code{nnkiboze-directory}, which is @file{~/News/} by default.  One
+contains the NOV header lines for all the articles in the group, and the
+other is an additional @file{.newsrc} to store information on what
+groups that have been searched through to find component articles.
+
+Articles that are marked as read in the nnkiboze group will have their
+NOV lines removed from the NOV file.
 
 @node nndir
 @subsection nndir
+@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
+it, you might treat it as a newsgroup.  The files have to have numerical
 names, of course.
 
-This situation is kinda special, so there's a shortcut for creating
-these "groups": @kbd{d} (@code{gnus-group-make-directory-group}) in the
-group buffer. You will be prompted for a directory to read.
+This might be an opportune moment to mention ange-ftp, that most
+wonderful of all wonderful Emacs packages.  When I wrote nndir, I didn't
+think much about it - a backend to read directories.  Big deal.
+
+ange-ftp changes that picture dramatically.  For instance, if you enter
+@file{/ftp/amanda} as the the directory name, ange-ftp will actually
+allow you to read this directory over at amanda as a newsgroup.
+Distributed news ahoy!
+
+nndir supports, and will use, NOV files if they are present.
+
+@node nndoc
+@subsection nndoc
+@cindex nndoc
+@cindex documentation group
+@cindex help group
+
+nndoc is a cute little thing that will let you read a single file as a
+newsgroup.  The file has to be divided into articles by the use of Unix
+mbox "From " lines.  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.
+
+@node nndigest
+@subsection nndigest
+@cindex nndigest
+@cindex digest groups
+
+nndigest is a bit odd.  It will use a buffer containing a valid digest
+as the basis of the group.
+
+These nndigest groups are rather ephemeral.  They will never store
+information on what articles you have read, and you can't really use
+them as foreign groups at all.  The only way to reach an nndigest group
+is to type @kbd{V D} on a digest in the summary buffer.
+
+When you have finished reading the digest and press @kbd{q}, you will be
+returned to the group from whence you came instead of going to the group
+buffer.
+
+Odd all over, as you can see, but somewhat useful.
 
 @node Mail
 @subsection Mail
+@cindex reading mail
+@cindex mail
 
 Reading mail with a newsreader - isn't that just plain WeIrD? But of
 course.
 
 @menu
-* Creating Mail Groups::         How to create mail groups (duh).
+* Creating Mail Groups::         How to create mail groups.
+* Mail & Procmail::              Reading mail groups that procmail create.
 * Expiring Old Mail Articles::   Getting rid of unwanted mail.
 @end menu
 
 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 you mail in.
+depends on what format you want to store your mail in.
 
 @menu
-* nnmbox::    Using the quite standard Un*x mbox.
-* nnrmail::   Many Emacs programs use the rmail babyl format.
+* nnmbox::    Using the (quite) standard Un*x mbox.
+* nnbabyl::   Many Emacs programs use the rmail babyl format.
 * nnml::      Store your mail in a private spool?
 * nnmh::      An mhspool-like backend useful for procmail people.
+* nnfolder::  Having one file for each group.
 @end menu
 
 @vindex nnmail-read-incoming-hook
@@ -851,6 +1320,11 @@ The mail backends all call @code{nnmail-read-incoming-hook} after
 reading new mail.  You can use this hook to notify any mail watch
 programs, if you want to.
 
+@vindex nnmail-spool-file
+@code{nnmail-spool-file} says where to look for new mail.  If this
+variable is @code{nil}, the mail backends will never attempt to fetch
+mail by themselves.
+
 Gnus gives you all the opportunity you want for shooting yourself in
 your foot.  Let's say you create a group that will contain all the mail
 you get from your boss.  And then you accidentally unsubscribe from the
@@ -863,26 +1337,27 @@ month's rent money.
 
 @node Creating Mail Groups
 @subsubsection Creating Mail Groups
+@cindex creating mail groups
 
 You can make Gnus read your personal, private, secret mail.
 
 You should first set @code{gnus-secondary-select-methods} to, for
-instance, @code{((nnmbox ""))}. When you start up Gnus, Gnus will ask
-this backend for what groups it has (@samp{mail.misc} by default) and
-subscribe it the normal way. (Which means you may have to look for it
-among the zombie groups, I guess, all depending on your
+instance, @code{((nnmbox ""))}.  When you start up Gnus, Gnus will ask
+this backend for what groups it carries (@samp{mail.misc} by default)
+and subscribe it the normal way.  (Which means you may have to look for
+it among the zombie groups, I guess, all depending on your
 @code{gnus-subscribe-newsgroup-method} variable.)
 
 @vindex nnmail-split-methods
 The you should set the variable @code{nnmail-split-methods} to specify
 how the incoming mail is to be split into groups.
 
-@example
+@lisp
 (setq nnmail-split-methods
   '(("mail.junk" "^From:.*Lars Ingebrigtsen")
     ("mail.crazzy" "^Subject:.*die\\|^Organization:.*flabby")
     ("mail.other" "")))
-@end example
+@end lisp
 
 This variable is a list of lists, where the first element of each of
 these lists contain the name of the mail group (they do not have to be
@@ -890,11 +1365,61 @@ called something beginning with @samp{"mail"}, by the way), and the
 second element is a regular expression used on the header of each mail
 to determine if it belongs in this mail group.
 
+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 *always* be @samp{""} so that it matches all mails.
+expression should *always* be @samp{""} so that it matches any mails
+that haven't been matched by any of the other regexps.
+
+@vindex nnmail-crosspost
+The mail backends 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.
+
+@node Mail & Procmail
+@subsubsection Mail & Procmail
+@cindex procmail
+
+Many people use @code{procmail} to split incoming mail into groups.  If
+you do that, you should set @code{nnmail-spool-file} to @code{nil} to
+make sure that the mail backends never ever try to fetch mail by
+themselves.
+
+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 that
+actually exists.  (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.)
+
+This means that you have to tell Gnus (and the backends) what groups
+exist by hand.
+
+Let's take the @code{nnfolder} backend as an example.  (This backend
+features one file as the basis of each group.)  
+
+The folders are located in @code{nnfolder-directory}, say,
+@file{~/Mail/}.  There are three folders, @file{foo}, @file{bar} and
+@file{mail.baz}.
+
+Go to the group buffer and type @kbd{M m}.  When prompted, answer
+@samp{foo} for the name, @samp{nnfolder} for the method and @samp{""}
+for the address.  Repeat twice for the two other groups, @samp{bar} and
+@code{mail.baz}.  Be sure to include all your mail groups.
+
+That's it.  You are now set to read your mail.
 
 @node Expiring Old Mail Articles
 @subsubsection Expiring Old Mail Articles
+@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
@@ -913,9 +1438,9 @@ 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 capitalization: IF you do NOT mark
-articles as EXPIRABLE, Gnus will NEVER delete those ARTICLES.
+will remain on your system until hell freezes over.  This bears
+repeating one more time, with some spurious capitalization: IF you do
+NOT mark articles as EXPIRABLE, Gnus will NEVER delete those ARTICLES.
 
 @vindex gnus-auto-expirable-newsgroups
 You do not have to mark articles as expirable by hand.  Groups that
@@ -927,10 +1452,10 @@ column in the summary buffer.
 Let's say you subscribe to a couple of mailing lists, and you want the
 articles you have read to disappear after a while:
 
-@example
+@lisp
 (setq gnus-auto-expirable-newsgroups 
       "^mail.nonsense-list\\|^mail.nice-list")
-@end example
+@end lisp
 
 @vindex nnmail-expiry-wait
 The @code{nnmail-expiry-wait} variable supplies the default time an
@@ -942,7 +1467,7 @@ 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:
 
-@example
+@lisp
 (setq nnmail-expiry-wait-function
       '(lambda (group)
         (cond ((string= group "mail.private")
@@ -951,10 +1476,17 @@ everywhere else:
                 1)
               (t
                 6))))
-@end example
+@end lisp
+
+@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.
 
 @node nnmbox
 @subsubsection nnmbox
+@cindex nnmbox
+@cindex unix mail box
 
 @vindex nnmbox-active-file
 @vindex nnmbox-mbox-file
@@ -964,19 +1496,29 @@ variable.  In addition, Gnus needs to store information about active
 articles.  The file specified by @code{nnmbox-active-file} will be used
 for that.
 
-@node nnrmail
-@subsubsection nnrmail
+nnmbox will add extra headers to each mail article to say which
+group it belongs in.
 
-@vindex nnrmail-active-file
-@vindex nnrmail-mbox-file
-The @dfn{nnrmail} backend will use a babyl mail box to store mail.  The
-path of the rmail mail box file is given by the @code{nnrmail-mbox-file}
+@node nnbabyl
+@subsubsection nnbabyl
+@cindex nnbabyl
+@cindex rmail mbox
+
+@vindex nnbabyl-active-file
+@vindex nnbabyl-mbox-file
+The @dfn{nnbabyl} backend will use a babyl mail box to store mail.  The
+path of the rmail mail box file is given by the @code{nnbabyl-mbox-file}
 variable.  In addition, Gnus needs to store information about active
-articles.  The file specified by @code{nnrmail-active-file} will be used
+articles.  The file specified by @code{nnbabyl-active-file} will be used
 for that.
 
+nnbabyl will add extra headers to each mail article to say which
+group it belongs in.
+
 @node nnml
 @subsubsection nnml
+@cindex nnml
+@cindex mail nov spool
 
 The spool mail format (@code{nnml}) isn't compatible with any other
 known format.  It should be used with some caution.
@@ -1000,23 +1542,53 @@ 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.
 
 @code{nnml} is probably the slowest backend when it comes to article
-splitting. It has to create lots of files, and it also generates NOV
-databases for the incoming mails. This makes is the fastest backend when
-it comes to reading mail.
+splitting.  It has to create lots of files, and it also generates NOV
+databases for the incoming mails.  This makes is the fastest backend
+when it comes to reading mail.
+
+@findex nnml-generate-nov-databases
+If your @code{nnml} groups and 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 finish.
 
 @node nnmh
 @subsubsection nnmh
+@cindex nnmh
+@cindex mh-e mail spool
 
 @code{nnmh} is just like @code{nnml}, except that is doesn't generate
-NOV databases and it doesn't keep an active file. This makes @code{nnmh}
-a *much* slower backend than @code{nnml}, but it also makes it easier to
-write procmail scripts for.
+NOV databases and it doesn't keep an active file.  This makes
+@code{nnmh} a *much* slower backend than @code{nnml}, but it also makes
+it easier to write procmail scripts for.
+
+@node nnfolder
+@subsubsection nnfolder
+@cindex nnfolder
+@cindex mbox folders
+
+@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.
+
+@vindex nnfolder-active-file
+@vindex nnfolder-directory
+@code{nnfolder-directory} says where to store these files, and
+@code{nnfolder-active-file} says where to store the @dfn{active}
+information.
 
 @node Listing Groups
 @section Listing Groups
+@cindex group listing
+
+These commands all list various slices of the groups that are available.
 
 @table @kbd
 @item l
+@item G s
+@kindex G s (Group)
 @kindex l (Group)
 @findex gnus-group-list-groups
 List all subscribed groups that have unread articles
@@ -1024,6 +1596,8 @@ List all subscribed groups that have unread articles
 command will list only groups of level ARG and lower.  By default, it
 only lists groups of level five or lower (ie. just subscribed groups).
 @item L
+@item G u
+@kindex G u
 @kindex L (Group)
 @findex gnus-group-list-all-groups
 List all subscribed and unsubscribed groups, whether they have unread
@@ -1031,18 +1605,28 @@ articles or not (@code{gnus-group-list-all-groups}).  If the numeric
 prefix is used, this command will list only groups of level ARG and
 lower.  By default, it lists groups of level seven or lower (ie. just
 subscribed and unsubscribed groups).
-@item C-c C-k
-@kindex C-c C-k (Group)
+@item k
+@kindex k (Group)
 @findex gnus-group-list-killed
 List all killed groups (@code{gnus-group-list-killed}).
-@item C-c C-z
-@kindex C-c C-z (Group)
+@item z
+@kindex z (Group)
 @findex gnus-group-list-zombies
 List all zombie groups (@code{gnus-group-list-zombies}).
+@item G m
+@kindex G m (Group)
+@findex gnus-group-list-matching
+List all subscribed groups with unread articles that match a regexp
+(@code{gnus-group-list-matching}). 
+@item G M
+@kindex G M (Group)
+@findex gnus-group-list-all-matching
+List groups that match a regexp (@code{gnus-group-list-all-matching}).
 @end table
 
 @node Group Maintenance
 @section Group Maintenance
+@cindex bogus groups
 
 @table @kbd
 @item b
@@ -1064,10 +1648,24 @@ process (if any) (@code{gnus-group-expire-articles}).
 @findex gnus-group-expire-all-groups
 Run all articles in all groups through the expiry process
 (@code{gnus-group-expire-all-groups}).
+@item C-c C-s
+@kindex C-c C-s (Group)
+@findex gnus-group-sort-groups
+@findex gnus-group-sort-by-level
+@findex gnus-group-sort-by-unread
+@findex gnus-group-sort-by-alphabet
+@vindex gnus-group-sort-function
+Sort the groups according to the function given by the
+@code{gnus-group-sort-function} variable
+(@code{gnus-group-sort-groups}).  Available sorting functions include
+@code{gnus-group-sort-by-alphabet} (the default),
+@code{gnus-group-sort-by-unread} and @code{gnus-group-sort-by-level}. 
 @end table
 
 @node Browse Foreign Server
 @section Browse Foreign Server
+@cindex foreign servers
+@cindex browsing servers
 
 @table @kbd
 @item B
@@ -1078,6 +1676,7 @@ then attempt to contact this server and let you browse the groups there
 (@code{gnus-group-browse-foreign-server}).
 @end table
 
+@findex gnus-browse-server-mode
 A new buffer with a list of available groups will appear.  This buffer
 will be use the @code{gnus-browse-server-mode}.  This buffer looks a bit
 (well, a lot) like a normal group buffer, but with one major difference
@@ -1087,6 +1686,9 @@ think may be interesting, and then you have to exit this buffer.  The
 new groups will be added to the group buffer, and then you can read them
 as you would any other group.
 
+Future versions of Gnus may possibly permit reading groups straight from
+the browse buffer.
+
 Here's a list of keystrokes available in the browse mode:
 
 @table @kbd
@@ -1095,7 +1697,6 @@ Here's a list of keystrokes available in the browse mode:
 @findex gnus-group-next-group
 Go to the next group (@code{gnus-group-next-group}).
 @item p
-@kindex C-p (Browse)
 @kindex p (Browse)
 @findex gnus-group-prev-group
 Go to the previous group (@code{gnus-group-prev-group}).
@@ -1117,14 +1718,17 @@ there) (@code{gnus-browse-describe-briefly}).
 
 @node Exiting Gnus
 @section Exiting Gnus
+@cindex exiting Gnus
 
-Yes, Gnus is exiting.
+Yes, Gnus is ex(c)iting.
 
 @table @kbd
 @item z
 @kindex z (Group)
 @findex gnus-group-suspend
-Suspend Gnus (@code{gnus-group-suspend}).
+Suspend Gnus (@code{gnus-group-suspend}).  This doesn't really exit Gnus,
+but it kills all buffers exept the Group buffer.  I'm not sure why this
+is a gain, but then who am I to judge.
 @item q
 @kindex q (Group)
 @findex gnus-group-exit
@@ -1140,6 +1744,15 @@ Quit Gnus without saving any startup files (@code{gnus-group-quit}).
 @code{gnus-suspend-gnus-hook} is called when you suspend Gnus and
 @code{gnus-exit-gnus-hook} is called when you quit Gnus.
 
+Note:
+
+@quotation
+Miss Lisa Cannifax, while sitting in English class, feels her feet go
+numbly heavy and herself fall into a hazy trance as the boy sitting
+behind her drew repeated lines with his pencil across the back of her
+plastic chair.
+@end quotation
+
 @node Misc Group Stuff
 @section Misc Group Stuff
 
@@ -1155,6 +1768,11 @@ level ARG and lower (@code{gnus-group-get-new-news}).
 @findex gnus-group-get-new-news-this-group
 Check whether new articles have arrived in the current group
 (@code{gnus-group-get-new-news-this-group}).
+@item M-f
+@kindex M-f (Group)
+@findex gnus-group-fetch-faq
+Try to fetch the FAQ for the current group
+(@code{gnus-group-fetch-faq}).
 @item R
 @kindex R (Group)
 @findex gnus-group-restart
@@ -1176,18 +1794,18 @@ Clear the dribble buffer (@code{gnus-group-clear-dribble}).
 @item D
 @kindex D (Group)
 @findex gnus-group-describe-group
-Give a description of the current group
-(@code{gnus-group-describe-group}).
+Describe the current group (@code{gnus-group-describe-group}).  If given
+a prefix, force Gnus to re-read the description from the server.
 @item C-c C-a
 @kindex C-c C-a (Group)
 @findex gnus-group-apropos
-Give a listing of all groups that have names that match a regexp
+List all groups that have names that match a regexp
 (@code{gnus-group-apropos}).
 @item C-c M-C-a 
 @kindex C-c M-C-a (Group)
 @findex gnus-group-description-apropos
-Give a listing of all groups that have names or descriptions that match
-a regexp (@code{gnus-group-description-apropos}).
+List all groups that have names or descriptions that match a regexp
+(@code{gnus-group-description-apropos}).
 @item a
 @kindex a (Group)
 @findex gnus-group-post-news
@@ -1204,6 +1822,11 @@ Transpose two groups (@code{gnus-group-transpose-groups}).
 @kindex V (Group)
 @findex gnus-version
 Display current Gnus version numbers (@code{gnus-version}).
+@item M-d
+@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 descriptoion file from the server.
 @item ?
 @kindex ? (Group)
 @findex gnus-group-describe-briefly
@@ -1221,6 +1844,7 @@ buffer in some strange, unnatural way.
 
 @node The Summary Buffer
 @chapter The Summary Buffer
+@cindex summary buffer
 
 A line for each article is displayed in the Summay buffer.  You can move
 around, read articles, post articles and reply to them.
@@ -1231,10 +1855,11 @@ around, read articles, post articles and reply to them.
 * Choosing Articles::           Reading articles.
 * Paging the Article::          Scrolling the current article.
 * Reply Followup and Post::     Posting articles.
-* Cancelling and Superceding::  "Whoops, I shouldn't have called him that."
+* Cancelling and Superseding::  "Whoops, I shouldn't have called him that."
 * Ticking and Marking::         Marking articles as read, expirable, etc.
 * Threading::                   How threads are made.
 * Exiting the Summary Buffer::  Returning to the Group buffer.
+* Process/Prefix::              A convention used by many treatment commands.
 * Saving Articles::             Ways of customizing article saving.
 * Decoding Articles::           Gnus can treat series of (uu)encoded articles.
 * Various Article Stuff::       Various stuff dealing with articles.
@@ -1247,13 +1872,37 @@ around, read articles, post articles and reply to them.
 
 @node Summary Buffer Format
 @section Summary Buffer Format
+@cindex summary buffer format
+
+@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.
+@end menu
+
+@findex mail-extract-address-components
+@findex gnus-extract-address-components
+@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 From
+header.  Two pre-defined function 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.
+
+@vindex gnus-summary-same-subject
+@code{gnus-summary-same-subject} is a string indicating that the current
+article has the same subject as the previous.  This string will be used
+with those specs that require it.
+
+@node Summary Buffer Lines
+@subsection Summary Buffer Lines
 
 @vindex gnus-summary-line-format
 You can change the format of the lines in the summary buffer by changing
 the @code{gnus-summary-line-format} variable.  It works along the same
 lines a a normal @code{format} string, with some extensions.
 
-The default string is @samp{"%U%R%X%i %I%[%4L: %-20,20n%] %s\n"}.
+The default string is @samp{"%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"}.
 
 The following format specification characters are understood:
 
@@ -1298,6 +1947,8 @@ Expirable
 Replied
 @item i
 Score
+@item z
+Zcore
 @item x
 Xref
 @item D
@@ -1308,12 +1959,33 @@ Message-ID
 References
 @item x
 Xref
+@item u
+User defined specifier.  The next character in the format string should
+be a letter.  @sc{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 summary just like information from any other
+summary specifier.
 @end table
 
-No elements are required, except the @samp{%U}, @samp{%R}, @samp{%X} and
-@samp{%i} fields which have to be at the beginning of the line for
-reasons of efficiency.  If you try to remove those, or change them,
-you'll probably end up with a mess, at least in this version of Gnus.
+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,
+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 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.
+
+@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
@@ -1338,8 +2010,10 @@ and just as @samp{<%U more>} if there are just unread articles and no
 unselected ones.
 @end table
 
+
 @node Summary Manouvering
 @section Summary Manouvering
+@cindex summary movement
 
 All the straight movement commands understand the numeric prefix and
 behave pretty much as you'd expect. 
@@ -1347,59 +2021,58 @@ behave pretty much as you'd expect.
 None of these commands select articles.
 
 @table @kbd
-@item down
-@kindex down (Summary)
-@findex gnus-summary-next-subject
-Go to the next subject line (@code{gnus-summary-next-subject}).
-@item up
-@kindex up (Summary)
-@findex gnus-summary-prev-subject
-Go to the previous subject line (@code{gnus-summary-prev-subject}).
+@item G M-n
 @item M-n
 @kindex M-n (Summary)
+@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}). 
+@item G M-p
 @item M-p
 @kindex M-p (Summary)
+@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 g
 @item j
 @kindex j (Summary)
+@kindex G g (Summary)
 @findex gnus-summary-goto-subject
 Ask for an article number and then go to this summary line
 (@code{gnus-summary-goto-subject}). 
-@item l
-@kindex l (Summary)
-@findex gnus-summary-goto-last-article
-Go to the summary line of the previous article
-(@code{gnus-summary-goto-last-article}).
 @end table
 
 @vindex gnus-auto-select-next
 If you are at the end of the group and issue one of the movement
 commands, Gnus will offer to go to the next group.  If
-@code{gnus-auto-select-next} is t and the next group is empty, Gnus
-will exit summary mode and return to the group buffer.  If this
-variable is neither t nor nil, Gnus will select the next group, no
-matter if it has any unread articles or not.  As a special case, if this
-variable equals @code{quietly}, Gnus will select the next group
-without asking for confirmation.  Also see @code{gnus-keep-same-level}. 
+@code{gnus-auto-select-next} 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 if it has any unread articles or not.  As a special
+case, if this variable equals @code{quietly}, Gnus will select the next
+group without asking for confirmation.  Also see
+@code{gnus-keep-same-level}.
+
+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.
 
 @vindex gnus-auto-center-summary
-If @code{gnus-auto-center-summary} is non-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 do simply not like
-this un-Emacsism, you can set this variable to nil to get the normal
-Emacs scrolling action.
+If @code{gnus-auto-center-summary} is 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 do simply not
+like this un-Emacsism, you can set this variable to @code{nil} to get
+the normal Emacs scrolling action.
 
 @node Choosing Articles
 @section Choosing Articles
+@cindex selecting articles
 
-All the movement commands understand the numeric prefix.
-
-All the following commands select an article.
+None of the following movement commands understand the numeric prefix,
+and they all select and display an article.
 
 @table @kbd
 @item SPACE
@@ -1407,56 +2080,100 @@ All the following commands select an article.
 @findex gnus-summary-next-page
 Select the current article, or, if that one's read already, the next
 unread article (@code{gnus-summary-next-page}).
+@item G n
 @item n
 @kindex n (Summary)
+@kindex G n (Summary)
 @findex gnus-summary-next-unread-article
 Go to next unread article (@code{gnus-summary-next-unread-article}).
+@item G p
 @item p
 @kindex p (Summary)
 @findex gnus-summary-prev-unread-article
 Go to previous unread article (@code{gnus-summary-prev-unread-article}).
+@item G N
 @item N
 @kindex N (Summary)
+@kindex G N (Summary)
 @findex gnus-summary-next-article
 Go to the next article (@code{gnus-summary-next-article}).
+@item G P
 @item P
 @kindex P (Summary)
+@kindex G P (Summary)
 @findex gnus-summary-prev-article
 Go to the previous article (@code{gnus-summary-prev-article}).
-@item M-C-n
-@kindex M-C-n (Summary)
+@item C-n
+@kindex C-n (Summary)
 @findex gnus-summary-next-same-subject
 Go to the next article with the same subject
 (@code{gnus-summary-next-same-subject}). 
-@item M-C-p
-@kindex M-C-p (Summary)
+@item C-p
+@kindex C-p (Summary)
 @findex gnus-summary-prev-same-subject
 Go to the previous article with the same subject
 (@code{gnus-summary-prev-same-subject}). 
+@item G f
 @item .
-@kindex . (Summary)
+@kindex G f  (Summary)
+@kindex .  (Summary)
 @findex gnus-summary-first-unread-article
-Go to the first unread article (@code{gnus-summary-first-unread-article}).
+Go to the first unread article
+(@code{gnus-summary-first-unread-article}).
+@item G b
+@item ,
+@kindex G b (Summary)
+@kindex , (Summary)
+Go to the article with the highest score
+(@code{gnus-summary-best-unread-article}). 
+@item G l
+@item l
+@kindex l (Summary)
+@kindex G l (Summary)
+@findex gnus-summary-goto-last-article
+Go to the summary line of the previous article
+(@code{gnus-summary-goto-last-article}).
+@item G p
+@kindex G p
+@findex gnus-summary-pop-article
+Pop an article off the summary history and go to the previous article
+(@code{gnus-summary-pop-article}).  This command differs from the
+command above in that you can pop as many previous articles off the
+history as you like.
 @end table
 
+Some variables that are relevant for moving and selecting articles:
+
+@table @code
+@item gnus-auto-extend-newsgroup
 @vindex gnus-auto-extend-newsgroup
 All the movement commands will try to go to the previous (or next)
 article, even if that article isn't displayed in the Summary buffer if
-@code{gnus-auto-extend-newsgroup} is non-nil.  Gnus will fetch the
-article from the server and present it in the article buffer.
-
+this variable is non-@code{nil}.  Gnus will then fetch the article from
+the server and display it in the article buffer.
+@item gnus-select-article-hook
 @vindex gnus-select-article-hook
-@code{gnus-select-article-hook} is called whenever an article is
-selected.  By default it makes any threads hidden under the current
-article visible.
-
+This hook is called whenever an article is selected.  By default it
+exposes any threads hidden under the selected article.
+@item gnus-mark-article-hook
 @vindex gnus-mark-article-hook
-@code{gnus-mark-article-hook} is called when an article is selected for
-the first time.  It is intended to be used for marking articles as read
-automatically when articles are selected.
+This hook is called when an article is selected for the first time.  It
+is intended to be used for marking articles as read automatically when
+articles are selected.
+@item gnus-visual-mark-article-hook
+@vindex gnus-visual-mark-article-hook
+This hook is run after selecting an article.  It is meant to be used for
+highlighting the article in some way.  It is not run if
+@code{gnus-visual} is @code{nil}.
+@item gnus-visual-summary-update-hook
+@vindex gnus-visual-summary-update-hook
+This hook is called when a summary line is changed.  It is not run if
+@code{gnus-visual} is @code{nil}.
+@end table
 
 @node Paging the Article
 @section Scrolling the Article
+@cindex article scrolling
 
 @table @kbd
 @item SPACE
@@ -1475,23 +2192,33 @@ Scoll the current article back one page (@code{gnus-summary-prev-page}).
 Scroll the current article one line forward
 (@code{gnus-summary-scroll-up}).
 @item <
+@item A <
 @kindex < (Summary)
+@kindex A < (Summary)
 @findex gnus-summary-beginning-of-article
 Scroll to the beginning of the article
 (@code{gnus-summary-beginning-of-article}).
 @item >
+@item A >
 @kindex > (Summary)
+@kindex A > (Summary)
 @findex gnus-summary-end-of-article
 Scroll to the end of the article (@code{gnus-summary-end-of-article}).
 @end table
 
 @node Reply Followup and Post
 @section Reply Followup and Post
+@cindex reply
+@cindex followup
+@cindex post
 
 @kindex C-c C-c (Post)
 All the commands for posting and mailing will put you in a post or mail
 buffer where you can edit the article all you like, before you send the
-article by pressing @kbd{C-c C-c}.
+article by pressing @kbd{C-c C-c}.  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. 
 
 @table @kbd
 @item a
@@ -1518,6 +2245,16 @@ Mail a reply to the author of the current article
 @findex gnus-summary-reply-with-original
 Mail a reply to the author of the current article and include the
 original message (@code{gnus-summary-reply-with-original}).
+@item b
+@kindex b (Summary)
+@findex gnus-summary-followup-and-reply
+Post a followup and send a reply to the current article
+(@code{gnus-summary-followup-and-reply}).
+@item B
+@kindex N (Summary)
+@findex gnus-summary-followup-and-reply-with-original
+Post a followup and send a reply to the current article and include the
+original message (@code{gnus-summary-followup-and-reply-with-original}).
 @item C-c C-f
 @kindex C-c C-f (Summary)
 @findex gnus-summary-mail-forward
@@ -1528,16 +2265,40 @@ Forward the current article to some other person
 @findex gnus-summary-mail-other-window
 Send a mail to some other person
 (@code{gnus-summary-mail-other-window}). 
+@item S M-f
+@kindex S M-f (Summary)
+@findex gnus-uu-digest-and-forward
+Digest the current series and forward the result using mail
+(@code{gnus-uu-digest-and-forward}). 
+@item S u
+@kindex S u (Summary)
+@findex gnus-uu-post-news
+Uuencode a file, split it up into parts, and post it as a series
+(@code{gnus-uu-post-news}). 
 @end table
 
+@table @code
+@item gnus-required-headers
 @vindex gnus-required-headers
 Gnus determines which headers it should generate in outgoing posts by
-consulting the @code{gnus-required-headers} variable.  This is a list of
-headers that Gnus makes sure is present in all outgoing posts before it
-tries to post them.
-
-@vindex gnus-followup-to-function
+consulting the this variable.  All headers mentioned in this list will
+either be generated automatically or prompted for before an article is
+posted. 
+@item gnus-post-method
+@vindex gnus-post-method
+If non-@code{nil}, Gnus will use this method instead of the default
+select method when posting.
+@item gnus-use-followup-to
+@vindex gnus-use-followup-to
+If @code{nil}, always ignore the Followup-To header.  If it is @code{t},
+use its value, but ignore the special value @samp{poster}, which will
+send the followup as a reply mail to the person you are responding to.
+If it is neither @code{nil} nor @code{t}, always use the Followup-To
+value.
+@item gnus-followup-to-function
+@item gnus-reply-to-function
 @vindex gnus-reply-to-function
+@vindex gnus-followup-to-function
 Gnus uses the normal methods to determine where replys and follow-ups
 are to go, but you can change the behaviour to suit your need by
 fiddling with the @code{gnus-reply-to-function} and
@@ -1547,59 +2308,83 @@ To take "reply" as an example: If you want the replies to go to the
 "sender" instead of the "from" in the group "mail.stupid-list", you
 could do something like this:
 
-@example
+@lisp
 (setq gnus-reply-to-function
       '(lambda (group)
         (cond ((string= group "mail.stupid-list")
                 (mail-fetch-field "sender"))
               (t
                nil))))
-@end example
+@end lisp
 
 These functions will be called with point in the buffer of the article
 that is being replied to (or followed up).
-
+@item gnus-signature-function
+@vindex gnus-signature-function
+If non-@code{nil}, this variable should be a function that returns a
+signature file name.  The function will be called with the name of the
+group being posted to.  If the function returns a string that doesn't
+correspond to a file, the string itself is inserted.  If the function
+returns @code{nil}, the @code{gnus-signature-file} variable will be used
+instead.
+@item gnus-signature-file
+@item mail-signature
 @vindex mail-signature
 @vindex gnus-signature-file
-If @code{gnus-signature-file} is non-nil, it should be the name of a
-file containing a signature (@samp{~/.signature} by default).  This
-signature will be appended to all outgoing post.  Most people find it
-more convenient to use @code{mail-signature}, which does the same, but
-inserts the signature into the buffer before you start editing the post
-(or mail).  So - if you have both of these variables set, you will get
-two signatures.
-
+If non-@code{nil}, this variable should be the name of a file containing
+a signature (@samp{~/.signature} by default).  This signature will be
+appended to all outgoing post.  Most people find it more convenient to
+use @code{mail-signature}, which does the same, but inserts the
+signature into the buffer before you start editing the post (or mail).
+So - if you have both of these variables set, you will get two
+signatures.
+
+Note that RFC1036 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 filter the signature away.  So
+don't remove those characters, even though you might feel that they ruin
+you beautiful design, like, totally.
+
+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.
+@item gnus-post-prepare-function
 @vindex gnus-post-prepare-function
-In any case, @code{gnus-post-prepare-function} is called with the name
-of the current group after the post buffer has been initialized, and can
-be used for inserting a signature.  Nice if you use different signatures
-in different groups.
-
+This function is called with the name of the current group after the
+post buffer has been initialized, and can be used for inserting a
+signature.  Nice if you use different signatures in different groups.
+@item gnus-auto-mail-to-author
 @vindex gnus-auto-mail-to-author
-If @code{gnus-auto-mail-to-author} is non-nil, Gnus will send a mail
-with a copy of all follow-ups to the authors of the articles you follow
-up.  It's nice in one way - you make sure that the person you are
-responding to gets your response.  Other people loathe this method and
-will hate you dearly for it, because it means that they will first get a
-mail, and then have to read the same article later when they read the
-news.  It is nil by default.
-
+If non-@code{nil}, Gnus will send a mail with a copy of all follow-ups
+to the authors of the articles you follow up.  It's nice in one way -
+you make sure that the person you are responding to gets your response.
+Other people loathe this method and will hate you dearly for it, because
+it means that they will first get a mail, and then have to read the same
+article later when they read the news.  It is @code{nil} by default.
+@item gnus-mail-send-method
 @vindex gnus-mail-send-method
-@code{gnus-mail-send-method} says how a mail should be mailed.  It uses
-the function in the @code{send-mail-function} as the default.
-
+This variable says how a mail should be mailed.  It uses the function in
+the @code{send-mail-function} variable as the default.
+@item gnus-prepare-article-hook
 @vindex gnus-prepare-article-hook
-@code{gnus-prepare-article-hook} is called before the header fields have
-been prepared.  By default it inserts the signature specified by
-@code{gnus-signature-file}. 
-
+This hook is called before the headers have been prepared.  By default
+it inserts the signature specified by @code{gnus-signature-file}.
+@item gnus-inews-article-hook
 @vindex gnus-inews-article-hook
-@code{gnus-inews-article-hook} is called right before the article is
-posted.  By default it handles FCC processing (ie. saving the article to
-a file.)
+This hook is called right before the article is posted.  By default it
+handles FCC processing (ie. saving the article to a file.)
+@item gnus-inews-article-header-hook
+@vindex gnus-inews-article-header-hook
+This hook is called after inserting the required headers in an article
+to be posted.  The hook is called from the @code{*post-news*} buffer,
+narrowed to the headers, and is intended for people who would like to
+insert additional headers, or just change headers in some way.
+@end table
 
-@node Cancelling and Superceding
+@node Cancelling and Superseding
 @section Cancelling Articles
+@cindex cancelling articles
+@cindex superseding articles
 
 Have you ever written something, and then decided that you really,
 really, really hadn't posted that? 
@@ -1631,7 +2416,7 @@ The same goes for superseding as for cancelling, only more so: Some
 sites do not honor superseding.  On those sites, it will appear that you
 have posted almost the same article twice.
 
-If you have just posted the article, and changed your mind right away,
+If you have just posted the article, and change your mind right away,
 there is a trick you can use to cancel/supersede the article without
 waiting for the article to appear on your site first.  You simply return
 to the post buffer (which is called @code{*post-buf*}).  There you will
@@ -1641,62 +2426,147 @@ header by substituting one of those words for @samp{Message-ID}.  Then
 just press @kbd{C-c C-c} to send the article as you would do normally.
 The previous article will be cancelled/superseded.
 
+Just remember, kids: There is no 'c' in 'supersede'.
+
 @node Ticking and Marking
 @section Ticking and Marking
+@cindex article marking
+@cindex article ticking
 
 There are several marks you can set on an article. 
 
-First you have the marks that decide the "readed-ness" (whoo,
-neato-keano neologism ohoy!) of the article. It can be unread, ticked,
-dormant or read, in ascending readed-ness ordering.
+You have marks that decide the "readed-ness" (whoo, neato-keano
+neologism ohoy!) of the article.  Alphabetic marks generally mean
+@dfn{read}, while non-alphabetic characters generally mean @dfn{unread}.
 
+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.
+@end menu
+
+There's a plethora of commands for manipulating these marks:
+
+@menu
+* Setting Marks::           How to set and remove marks.
+* Setting Process Marks::   How to mark articles for later processing.
+@end menu
+
+@node Unread Articles
+@subsection Unread Articles
+
+The following marks mark articles as unread, in one form or other.
+
+@vindex gnus-dormant-mark
+@vindex gnus-ticked-mark
+@table @samp
+@item !
 @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 save it.  Ticked articles have a @samp{-}
-in the first column.
+article forever, you'll have to save it.  Ticked articles have a
+@samp{!} (@code{gnus-ticked-mark}) in the first column.
+@item ?
+A @dfn{dormant} article is marked with a @samp{?}
+(@code{gnus-dormant-mark}), and will only appear in the summary buffer
+if there are followups to it.
+@item SPC
+An @dfn{unread} article is marked with a @samp{SPC}
+(@code{gnus-unread-mark}).  These are articles that haven't been read at
+all yet.
+@end table
 
-A @dfn{dormant} article is marked with a @samp{+}, and will only appear
-in the summary buffer if there are followups to it. 
+@node Read Articles
+@subsection Read Articles
+@cindex expirable mark
 
-Articles that are marked as read - are just that.  They have a @samp{D}
-in the first column.  Unread articles have a space in the first column.
+All the following marks mark articles as read.
 
-There are also some marks that do not affect readed-ness:
+@table @samp
+@item D
+Articles that are marked as read.  They have a @samp{D}
+(@code{gnus-dread-mark}) in the first column.  These are articles that the
+user has marked as read more or less manually.
+@item d
+Articles that are actually read are marked with @samp{d}
+(@code{gnus-read-mark}). 
+@item A
+Articles that were marked as read in previous sessions are now
+@dfn{ancient} and marked with @samp{A} (@code{gnus-ancient-mark}). 
+@item K
+Marked as killed ((@code{gnus-killed-mark})).
+@item X
+Marked as killed by kill files (@code{gnus-kill-file-mark}).
+@item Y
+Marked as read by having a too low score (@code{gnus-low-score-mark}).
+@item C
+Marked as read by a catch-up (@code{gnus-catchup-mark}).
+@item G
+Cancelled article (@code{gnus-cancelled-mark})
+@end table
+
+All these mark just mean that the article is marked as read,
+really.  They are interpreted differently by the adaptive scoring scheme,
+however. 
+
+One more special mark, though:
 
+@table @samp
+@item E
 You can also mark articles as @dfn{expirable} (or have them marked as
 such automatically).  That doesn't make much sense in normal groups,
 because a user does not control the expiring of news articles, but in
 mail groups, for instance, articles that are marked as @dfn{expirable}
-can be deleted by Gnus at any time.  Expirable articles have a @samp{X}
-in the third column.
+can be deleted by Gnus at any time.  Expirable articles are marked with
+@samp{E} (@code{gnus-expirable-mark}).
+@end table
+
+@node Other Marks
+@subsection Other Marks
+@cindex process mark
+@cindex bookmarks
 
-You can set a bookmark in the current article. Say you are reading a
+There are some marks that have nothing to do with whether the article is
+read or not.
+
+You can set a bookmark in the current article.  Say you are reading a
 long thesis on cat's urinary tracts, and have to go home for dinner
-before you've finished reading the thesis. You can then set a bookmark
+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.
 
 Finally we have the @dfn{process mark}.  A variety of commands react to
-the presence of the process mark.  For instance, @kbd{C-c C-v M-C-v}
-(@code{gnus-uu-decode-and-view-marked-articles}) will uudecode and view
-all artciles that have been marked with the process mark.  Articles
-marked with the process mark have a @samp{#} in the third column.
+the presence of the process mark.  For instance, @kbd{X u}
+(@code{gnus-uu-decode-uu}) will uudecode and view all articles that have
+been marked with the process mark.  Articles marked with the process
+mark have a @samp{#} in the second column.
+
+@node Setting Marks
+@subsection Setting Marks
+@cindex setting marks
 
 All the marking commands understand the numeric prefix.
 
 @table @kbd
+@item M t
 @item !
 @kindex ! (Summary)
-@findex gnus-summary-mark-as-unread-forward
-Tick the current article (@code{gnus-summary-mark-as-unread-forward}).
+@kindex M t (Summary)
+@findex gnus-summary-tick-article-forward
+Tick the current article (@code{gnus-summary-tick-article-forward}).
+@item M ?
 @item ?
 @kindex ? (Summary)
+@kindex M ? (Summary)
 @findex gnus-summary-mark-as-dormant
 Mark the current article as dormant
 (@code{gnus-summary-mark-as-dormant}).
+@item M d
 @item d
+@kindex M d (Summary)
 @kindex d (Summary)
 @findex gnus-summary-mark-as-read-forward
 Mark the current article as read
@@ -1712,217 +2582,326 @@ and then select the next unread article
 @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}).  
+@item M C
+@kindex M C (Summary)
+@findex gnus-summary-catchup
+Catchup the current group (@code{gnus-summary-catchup}).
+@item M C-c
+@kindex M C-c (Summary)
+@findex gnus-summary-catchup-all
+Catchup all articles in the current group (@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}).
+@item M c
 @item M-u
+@kindex M c (Summary)
 @kindex M-u (Summary)
 @findex gnus-summary-clear-mark-forward
 Clear tick and read marks from the current article
 (@code{gnus-summary-clear-mark-forward}).
-@item x
-@kindex x (Summary)
+@item M e
+@item E
+@kindex M e (Summary)
+@kindex E (Summary)
 @findex gnus-summary-mark-as-expirable
 Mark the current article as expirable
 (@code{gnus-summary-mark-as-expirable}).
-@item X
-@kindex X (Summary)
-@findex gnus-summary-unmark-as-expirable
-Remove the expiry mark from the current article
-(@code{gnus-summary-unmark-as-expirable}). 
-@item b
-@kindex b (Summary)
+@item M b
+@kindex M b (Summary)
 @findex gnus-summary-set-bookmark
 Set a bookmark in the current article
 (@code{gnus-summary-set-bookmark}).
-@item B
-@kindex B (Summary)
+@item B
+@kindex B (Summary)
 @findex gnus-summary-remove-bookmark
 Remove the bookmark from the current article
 (@code{gnus-summary-remove-bookmark}).
+@item M M-r
 @item M-d
+@kindex M M-r (Summary)
 @kindex M-d (Summary)
-@findex gnus-summary-delete-marked-as-read
+@findex gnus-summary-remove-lines-marked-as-read
 Expunge all deleted articles from the summary buffer
-(@code{gnus-summary-delete-marked-as-read}). 
+(@code{gnus-summary-remove-lines-marked-as-read}). 
+@item M M-C-r
 @item M-C-d
+@kindex M M-C-r (Summary)
 @kindex M-C-d (Summary)
-@findex gnus-summary-delete-marked-with
+@findex gnus-summary-remove-lines-marked-with
 Ask for a mark and then expunge all articles that have been marked with
-that mark (@code{gnus-summary-delete-marked-with}).
-@item C-c M-C-s
-@kindex C-c M-C-s (Summary)
+that mark (@code{gnus-summary-remove-lines-marked-with}).
+@item M S
+@kindex M S (Summary)
 @findex gnus-summary-show-all-expunged
 Display all expunged articles (@code{gnus-summary-show-all-expunged}).
-@item M-+
-@kindex M-+ (Summary)
+@item M D
+@kindex M D (Summary)
 @findex gnus-summary-show-all-dormant
 Display all dormant articles (@code{gnus-summary-show-all-dormant}).
+@item M M-D
+@kindex M M-D (Summary)
+@findex gnus-summary-hide-all-dormant
+Hide all dormant articles (@code{gnus-summary-hide-all-dormant}).
+@item M s k
+@kindex M s k (Summary)
+@findex gnus-summary-kill-below
+Kill all articles with scores below the default score (or below the
+numeric prefix) (@code{gnus-summary-kill-below}).
+@item M s c
+@kindex M s c (Summary)
+@findex gnus-summary-clear-above
+Clear all marks from articles with scores over the default score (or
+over the numeric prefix) (@code{gnus-summary-clear-above}).
+@item M s u
+@kindex M s u (Summary)
+@findex gnus-summary-tick-above
+Tick all articles with scores over the default score (or over the
+numeric prefix) (@code{gnus-summary-clear-above}).
+@item M s m
+@kindex M s m (Summary)
+@findex gnus-summary-mark-above
+Prompt for a mark, and mark all articles with scores over the default
+score (or over the numeric prefix) with this mark
+(@code{gnus-summary-clear-above}).
 @end table
 
-There are a few functions for setting the process mark:
+The @code{gnus-summary-goto-unread} variable controls what action should
+be taken after setting a mark.  If non-@code{nil}, point will move to
+the next/previous unread article.  If @code{nil}, point will just move
+one line up or down.
+
+@node Setting Process Marks
+@subsection Setting Process Marks
+@cindex setting process marks
 
 @table @kbd
 @item #
+@item M p
 @kindex # (Summary)
-@findex gnus-summary-mark-article-as-processable
+@kindex M p p (Summary)
+@findex gnus-summary-mark-as-processable
 Mark the current article with the process mark
-(@code{gnus-summary-mark-article-as-processable}). 
-@findex gnus-summary-unmark-article-as-processable
+(@code{gnus-summary-mark-as-processable}). 
+@findex gnus-summary-unmark-as-processable
 @item M-#
+@item M p u 
 @kindex M-# (Summary)
+@kindex M p u (Summary)
 Remove the process mark from the current article
-(@code{gnus-summary-unmark-article-as-processable}). 
+(@code{gnus-summary-unmark-as-processable}). 
 @item C-c M-#
+@item M p U
 @kindex C-c M-# (Summary)
-@findex gnus-summary-unmark-all-articles-as-processable
+@kindex M p U (Summary)
+@findex gnus-summary-unmark-all-processable
 Remove the process mark from all articles
-(@code{gnus-summary-unmark-all-articles-as-processable}). 
-@item C-c C-v C-r 
-@kindex C-c C-v C-r  (Summary)
+(@code{gnus-summary-unmark-all-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}). 
-@item C-c C-v r
-@kindex C-c C-v r (Summary)
+@item M p r
+@kindex M p r (Summary)
 @findex gnus-uu-mark-region
-Mark articles in the region (@code{gnus-uu-mark-region}).
-@item C-c C-v t
-@kindex C-c C-v t (Summary)
+Mark articles in region (@code{gnus-uu-mark-region}).
+@item M p t
+@kindex M p t (Summary)
 @findex gnus-uu-mark-thread
 Mark all articles in the current (sub)thread
 (@code{gnus-uu-mark-thread}).
+@item M p s
+@kindex M p s (Summary)
+@findex gnus-uu-mark-series
+Mark all articles in the current series (@code{gnus-uu-mark-series}).
+@item M p S
+@kindex M p S (Summary)
+@findex gnus-uu-mark-sparse
+Mark all series that have already had some articles marked
+(@code{gnus-uu-mark-sparse}).
+@item M p a
+@kindex M p a (Summary)
+@findex gnus-uu-mark-all
+Mark all articles in series order (@code{gnus-uu-mark-series}).
 @end table
 
-@findex gnus-uu-marked-universal-argument
-@kindex C-c C-v C-u (Summary)
-Finally, we have @kbd{C-c C-v C-u}
-(@code{gnus-uu-marked-universal-argument}) that will perform any
-operation on all articles that have been marked with the process mark. 
+@findex gnus-summary-universal-argument
+@kindex u (Summary)
+Finally, we have @kbd{V u} (@code{gnus-summary-universal-argument}) that
+will perform any operation on all articles that have been marked with
+the process mark.
 
 @node Threading
 @section Threading
+@cindex threading
+@cindex article threading
 
-Gnus @dfn{threads} articles by default.  @dfn{Threading} is to put
-replies to articles directly after the articles they reply to - in a
-hierarchial fashion.
+Gnus threads articles by default.  @dfn{To thread} is to put replies to
+articles directly after the articles they reply to - in a hierarchical
+fashion.
 
 @menu
 * Customizing Threading::     Variables you can change to affect the threading.
-* Threading Commands::        Thread based commands in the summary buffer.
+* Thread Commands::           Thread based commands in the summary buffer.
 @end menu
 
 @node Customizing Threading
 @subsection Customizing Threading
+@cindex customizing threading
 
 @table @code
 @item gnus-show-threads
 @vindex gnus-show-threads
-If this variable is nil, no threading will be done, and all of the rest
-of the variables here will have no effect.  Turning threading off will
-speed group selection up a bit, but it is sure to make reading
+If this variable is @code{nil}, no threading will be done, and all of
+the rest of the variables here will have no effect.  Turning threading
+off will speed group selection up a bit, but it is sure to make reading
 slower and more awkward.
 @item gnus-fetch-old-headers
 @vindex gnus-fetch-old-headers
-If non-nil, Gnus will attempt to build old threads by fetching more old
-headers - headers to articles that are marked as read. This only works
-if the server you are using supports XOVER. Also remember that if the
+If non-@code{nil}, Gnus will attempt to build old threads by fetching
+more old headers - headers to articles that are marked as read.  If it
+has the value `some', only enough headers to connect otherwise loose
+threads will be displayed.  Fetching old headers only works if the
+select method you are using supports XOVER.  Also remember that if the
 root of the thread has been expired by the server, there's not much Gnus
 can do about that.
 @item gnus-gather-loose-threads
 @vindex gnus-gather-loose-threads
-If non-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 it
-in a previous session.
+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 it or marked it as read in a previous session.
+@item gnus-summary-gather-subject-limit
+If this variable is @code{nil}, the entire subject line will be used to
+gather loose threads.  If you would limit this to the 20 first
+characters of the subjects, set this variable to 20.
 @item gnus-summary-make-false-root
 @vindex gnus-summary-make-false-root
 When there is no real root of a thread, Gnus will have to fudge
-something. This variable says what method Gnus should use while
-fudging. There are four possible value:
+something.  This variable says what method Gnus should use while
+fudging.  There are four possible value:
 
 @table @code
 @item adopt
-Gnus will make the first of the orphaned articles the parent. This
-parent will adopt all the other articles. The adopted articles will be
-marked as such by pointy brackeds instead of square brackets.
+Gnus will make the first of the orphaned articles the parent.  This
+parent will adopt all the other articles.  The adopted articles will be
+marked as such by pointy brackeds instead of square brackets.  This is
+the default value.
 @item dummy
-Gnus will create a dummy that will stand in as the parent. This dummy
+Gnus will create a dummy that will stand in as the parent.  This dummy
 will be displayed on a line of its own, but it does not correspond to
 any real article.
 @item empty
 Gnus won't actually make any article the parent, but simply leave the
-subject field of all orphans except the first empty. (It will use
+subject field of all orphans except the first empty.  (It will use
 @code{gnus-summary-same-subject} as the subject.)
 @item nil
-Don't make any article parent at all.
+Don't make any article parent at all.  Just gather the threads and
+display them after one another.
 @end table
 
 @item gnus-thread-hide-subtree
 @vindex gnus-thread-hide-subtree
-If non-nil, all subtrees will be hidden when the summary buffer is
-generated. 
+If non-@code{nil}, all subtrees will be hidden when the summary buffer
+is generated.
 @item gnus-thread-hide-killed
 @vindex gnus-thread-hide-killed
-if you kill a thread and this variable is non-nil, the subtree will be
-hidden. 
+if you kill a thread and this variable is non-@code{nil}, the subtree
+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-nil, the change in subject is ignored.  If it is
-nil, which is the default, a change in the subject will result in a new
-thread. 
+this variable is non-@code{nil}, the change in subject is ignored.  If
+it is @code{nil}, which is the default, 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 which says how many spaces to indent a thread.  The
+This is a number that how much each subthread should be indented.  The
 default is @samp{4}.
 @end table
 
-@node Threading Commands
-@subsection Threading Commands
+@node Thread Commands
+@subsection Thread Commands
+@cindex thread commands
 
 @table @kbd
+@item T k
 @item M-C-k
+@kindex T k (Summary)
 @kindex M-C-k (Summary)
 @findex gnus-summary-kill-thread
 Mark all articles under the current one as read
 (@code{gnus-summary-kill-thread}).  If the prefix argument is positive,
 remove all marks.  If the prefix argument is negative, tick articles.
-@item M-C-t
-@kindex M-C-t (Summary)
+@item T l
+@item M-C-l
+@kindex T l (Summary)
+@kindex M-C-l (Summary)
+@findex gnus-summary-lower-thread
+Lower the score of the current thread
+(@code{gnus-summary-lower-thread}). 
+@item T i
+@kindex T i (Summary)
+@findex gnus-summary-raise-thread
+Increase the score of the current thread
+(@code{gnus-summary-raise-thread}).
+@item T #
+@kindex T # (Summary)
+@findex gnus-uu-mark-thread
+Mark the current thread with the process mark
+(@code{gnus-uu-mark-thread}).
+@item T T
+@kindex T T (Summary)
 @findex gnus-summary-toggle-threads
 Toggle showing threads (@code{gnus-summary-toggle-threads}).
-@item M-C-s
-@kindex M-C-s (Summary)
+@item s
+@kindex s (Summary)
 @findex gnus-summary-show-thread
 Show the thread hidden under the current article, if any
 (@code{gnus-summary-show-thread}). 
-@item M-C-h
-@kindex M-C-h (Summary)
+@item h
+@kindex h (Summary)
 @findex gnus-summary-hide-thread
 Hide the current (sub)thread (@code{gnus-summary-hide-thread}).
+@item T S
+@kindex T S (Summary)
+@findex gnus-summary-show-all-threads
+Show all hidden threads (@code{gnus-summary-show-all-threads}).
+@item T H
+@kindex T H (Summary)
+@findex gnus-summary-hide-all-threads
+Hide all threads (@code{gnus-summary-hide-all-threads}).
 @end table
 
 The following commands are all thread movement commands.  They all
 understand the numeric prefix.
 
 @table @kbd
-@item M-C-f
-@kindex M-C-f (Summary)
+@item T n
+@kindex T n (Summary)
 @findex gnus-summary-next-thread
 Go to the next thread (@code{gnus-summary-next-thread}).
-@item M-C-b
-@kindex M-C-b (Summary)
+@item T p
+@kindex T p (Summary)
 @findex gnus-summary-prev-thread
 Go to the previous thread (@code{gnus-summary-prev-thread}).
-@item M-C-d
-@kindex M-C-d (Summary)
+@item d
+@kindex d (Summary)
 @findex gnus-summary-down-thread
 Descend the thread (@code{gnus-summary-down-thread}).
-@item M-C-u
-@kindex M-C-u (Summary)
+@item u
+@kindex u (Summary)
 @findex gnus-summary-up-thread
 Ascend the thread (@code{gnus-summary-up-thread}).
 @end table
 
 @node Exiting the Summary Buffer
 @section Exiting the Summary Buffer
+@cindex summary exit
+
+Exiting from the summary buffer will normally update all info on the
+group and return you to the group buffer. 
 
 @table @kbd
 @item q
@@ -1947,18 +2926,26 @@ Mark all articles in the group as read and exit
 group.  
 
 @vindex gnus-use-cross-reference
-When you exit the summary buffer, the data on the current group will
-be updated (which articles you have read, which articles you have
-replied to, etc.) If the @code{gnus-use-cross-reference} variable is
-non-nil, articles that are cross-referenced to this group, and are
-marked as read, will also be marked as read in the other groups they
-were cross-posted to.  This ensures that you'll never have to read the
-same article more than once.
-
-Unless, of course, somebody has posted it to several groups
-separately. If so, send them a nasty-gram.
-
-One other thing that may cause Gnus to not do the cross-posting thing
+When you exit the summary buffer, the data on the current group will be
+updated (which articles you have read, which articles you have replied
+to, etc.) If the @code{gnus-use-cross-reference} variable is @code{t}, articles
+that are cross-referenced to this group, and are marked as read, will
+also be marked as read in the other subscribed groups they were
+cross-posted to.   If this variable is neither @code{nil} nor @code{t}, the
+article will be marked as read in both subscribed and unsubscribed
+groups. 
+
+Marking cross-posted articles as read ensures that you'll never have to
+read the same article more than once.  Unless, of course, somebody has
+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.
+
+Remember: Cross-posting is kinda ok, but posting the same article
+separately to several groups is not.
+
+One thing that may cause Gnus to not do the cross-posting thing
 correctly is if you use an NNTP server that supports xover (which is
 very nice, because it speeds things up considerably) which does not
 include the Xref header in its NOV lines.  This is Evil, but it's
@@ -1970,20 +2957,49 @@ unable to use the cross reference mechanism.
 
 @vindex gnus-nov-is-evil
 If you want Gnus to get the Xrefs right all the time, you have to set
-@code{gnus-nov-is-evil} to t, which slows things down considerably. 
+@code{gnus-nov-is-evil} to @code{t}, which slows things down considerably. 
 
 C'est la vie.
 
+@node Process/Prefix
+@section Process/Prefix
+@cindex process/prefix convention
+
+Many functions, among them functions for moving articles, decoding
+articles and saving articles use what is known as the
+@dfn{Process/Prefix convention}.
+
+This is a method for figuring out what articles that the user wants the
+command to be performed on.
+
+It goes like this:
+
+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.
+
+If there is no numeric prefix, but some articles are marked with the
+process mark, perform the operation on the articles that are marked with
+the process mark.
+
+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 Saving Articles
 @section Saving Articles
+@cindex saving articles
 
 Gnus can save articles in a number of ways.  Below is the documentation
 for saving articles in a fairly straight-forward fashion (ie. little
 processing of the article is done before it is saved).  For a different
-approach (uudecoding, unsharing, digesting) see gnus-uu.
+approach (uudecoding, unsharing) see gnus-uu.  @xref{Decoding Articles}.
 
 @vindex gnus-save-all-headers
-If @code{gnus-save-all-headers} is non-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.
 
 @table @kbd
@@ -1993,11 +3009,14 @@ unwanted headers before saving the article.
 Save the current article (@code{gnus-summary-save-article}).
 @item C-o
 @kindex C-o (Summary)
-@findex gnus-summary-save-rmail
-Save the current article in rmail format
-(@code{gnus-summary-save-rmail}). 
+@findex gnus-summary-save-article-mail
+Save the current article in mail format
+(@code{gnus-summary-save-article-mail}). 
 @end table
 
+Both these command use the process/prefix convention
+(@pxref{Process/Prefix}). 
+
 @vindex gnus-default-article-saver
 You can customize the @code{gnus-default-article-saver} variable to make
 Gnus what you want it to.  You can use any of the four ready-made
@@ -2006,9 +3025,9 @@ functions below, or you can create your own.
 @table @code
 @item gnus-summary-save-in-rmail
 @vindex gnus-summary-save-in-rmail
-This is the format Gnus uses by default, @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}.
+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}.
 @item gnus-summary-save-in-mail
 @vindex gnus-summary-save-in-mail
 Save in a Unix mail (mbox) file.  Uses the function in the
@@ -2031,7 +3050,7 @@ in the @code{gnus-article-save-directory}, which is initialized from the
 
 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
-available functions that generates names:
+available functions that generate names:
 
 @table @code
 @item gnus-Numeric-save-name
@@ -2050,22 +3069,30 @@ Generates file names that look like @samp{~/News/alt.andrea-dworkin}.
 
 @vindex gnus-use-long-file-name
 Finally, you have the @code{gnus-use-long-file-name} variable.  If it is
-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 (@samp{~/News/alt/andrea-dworkin} instead of
+@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
+(@samp{~/News/alt/andrea-dworkin} instead of
 @samp{~/News/alt.andrea-dworkin}.)
 
 @node Decoding Articles
 @section Decoding Articles
+@cindex decoding articles
+
+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.
+* Shared Articles::       Unshar articles.
+@end menu
 
-Gnus has a plethora of functions for handling series of (uu)encoded
-articles.  Gnus can find out by itself what articles belong to one
-series, decode all the articles and unpack/view/save the resulting
-file(s).  All these functions belong to the `gnus-uu' package and are
-reached from the summary buffer as three-key keystrokes: @key{C-c C-v
-KEY}.  That last key varies, of course, but all these functions use the
-@key{C-c C-v} prefix keystroke.
+All these functions use the process/prefix convention
+(@pxref{Process/Prefix}) for finding out what articles to work on, with
+the extension that a "single article" means "a single series".  Gnus can
+find out by itself what articles belong to one series, decode all the
+articles and unpack/view/save the resulting file(s).
 
 Gnus guesses what articles are in the series according to the following
 simplish rule: The subjects must be (nearly) identical, except for the
@@ -2079,268 +3106,77 @@ Subjects that are nonstandard, like @samp{cat.gif (2/3) Part 6 of a
 series}, will not be properly recognized by any of the automatic viewing
 commands, and you have to mark the articles manually with @key{#}.
 
-@menu
-* Decoding Commands::           Decoding in various ways.
-* Setting the Process Mark::    You can mark which articles to work on.
-* Other Related Commands::      Other related commands.
-* Viewing Files::               You can view the resulting decoded files.
-* Decoding Variables::          No, you do not have to decode any variables.
+@menu 
+* Decoding Variables::     Variables for a happy decoding.
+* Viewing Files::          You want to look at the result of the decoding?
 @end menu
 
-@node Decoding Commands
-@subsection Decoding Commands
-
-All the keystrokes for decoding follow a strict pattern. 
-
-@table @key
-@item C-c C-v C-KEY
-This is a function for decoding and viewing.
-@item C-c C-v KEY
-This is a function for decoding and saving.
-@item C-c C-v M-C-KEY
-This is a function for decoding and viewing marked articles.
-@item C-c C-v M-KEY
-This is a function for decoding and saving marked articles.
-@end table
-@menu
-* Decoding With uudecode::         The most common encoding on the net.
-* Decoding With unshar::           This is used some in source groups.
-* Decoding With Other Decoders::   Binhex and plain save.
-@end menu
+@node Uuencoded Articles
+@subsection Uuencoded Articles
+@cindex uudecode
+@cindex uuencoded articles
 
-@node Decoding With uudecode
-@subsubsection Decoding With uudecode
-
-@table @key
-@item C-c C-v C-v
-@kindex C-c C-v C-v (Summary)
-@findex gnus-uu-decode-and-view
-Decode and view the series of articles that the current article is a
-part of (@code{gnus-uu-decode-and-view}). 
-@item C-c C-v v
-@kindex C-c C-v v (Summary)
+@table @kbd
+@item X u
+@kindex X u (Summary)
+@findex gnus-uu-decode-uu
+Uudecodes the current series (@code{gnus-uu-decode-uu}).
+@item X U
+@kindex X U (Summary)
 @findex gnus-uu-decode-and-save
-Decode and save the series of articles that the current article is a
-part of (@code{gnus-uu-decode-and-save}). 
-@item C-c C-v M-C-v
-@kindex C-c C-v M-C-v (Summary)
-@findex gnus-uu-marked-decode-and-view
-Decode and view the marked articles
-(@code{gnus-uu-marked-decode-and-view}). 
-@item C-c C-v M-v
-@kindex C-c C-v M-v (Summary)
-@findex gnus-uu-marked-decode-and-view
-Decode and save the marked articles
-(@code{gnus-uu-marked-decode-and-view}). 
-@item C-c C-v C-w
-@kindex C-c C-v C-w (Summary)
-@findex gnus-uu-decode-and-view-all-articles
-Decode and view all articles in the group
-(@code{gnus-uu-decode-and-view-all-articles}).  
-@item C-c C-v w
-@kindex C-c C-v w (Summary)
-@findex gnus-uu-decode-and-save-all-articles
-Decode and save all articles in the group
-(@code{gnus-uu-decode-and-save-all-articles}).  
-@item C-c C-v M-C-w
-@kindex C-c C-v M-C-w (Summary)
-@findex gnus-uu-decode-and-view-all-marked-files
-Decode and view all series of articles that are marked
-(@code{gnus-uu-decode-and-view-all-marked-files}).  
-@item C-c C-v M-w
-@kindex C-c C-v M-w (Summary)
-@findex gnus-uu-decode-and-save-all-marked-files
-Decode and save all series of articles that are marked
-(@code{gnus-uu-decode-and-save-all-marked-files}).  
-@item C-c C-v C-a
-@kindex C-c C-v C-a (Summary)
-@findex gnus-uu-decode-and-view-all-articles
-Decode and view all unread articles in the group
-(@code{gnus-uu-decode-and-view-all-articles}).  
-@item C-c C-v a
-@kindex C-c C-v a (Summary)
-@findex gnus-uu-decode-and-save-all-articles
-Decode and save all unread articles in the group
-(@code{gnus-uu-decode-and-save-all-articles}).  
-@item C-c C-v C-b
-@kindex C-c C-v C-b (Summary)
-@findex gnus-uu-decode-and-show-in-buffer
-Decode the current article and show the result in the article
-buffer.  This might be useful if somebody has encoded (parts of) an
-article, for some strange reason
-(@code{gnus-uu-decode-and-show-in-buffer}). 
-@end table
-
-The @code{gnus-uu-decode-and-save-all-marked-files} need some
-explanation.  It allows you to mark all articles that are part of series
-of articles you are interested in in a group.  You only have to mark
-one article for each series of articles you want, and then you call this
-function, which will find all articles that are part of the series you
-want.  Is that clear? And they say it's a stupid idea getting drunk
-before writing documentation! Bah! 
-
-@node Decoding With unshar
-@subsubsection Decoding With unshar
-
-Using @code{unshar} introduces rather large security holes - it actually
-runs the code it finds in the articles.  So you should, at least, peek
-through the articles you want to unshar before using these functions.
+Uudecodes and saves the current series (@code{gnus-uu-decode-and-save}).
+@item X v u
+@kindex X v u (Summary)
+@findex gnus-uu-decode-uu-view
+Uudecodes and views the current series (@code{gnus-uu-decode-uu-view}).
+@item X v U
+@kindex X v U (Summary)
+@findex gnus-uu-decode-uu-and-save-view
+Uudecodes, views and saves the current series
+(@code{gnus-uu-decode-uu-and-save-view}). 
+@end table
 
-@table @kbd
-@item C-c C-v C-s
-@kindex C-c C-v C-s (Summary)
-@findex gnus-uu-shar-and-view
-@kindex C-c C-v C-s (Summary)
-@findex gnus-uu-shar-and-view
-Unshar and view the series of articles that the current article is a
-part of (@code{gnus-uu-shar-and-view}). 
-@item C-c C-v s
-@kindex C-c C-v s (Summary)
-@findex gnus-uu-shar-and-save
-@kindex C-c C-v s (Summary)
-@findex gnus-uu-shar-and-save
-Unshar and save the series of articles that the current article is a
-part of (@code{gnus-uu-shar-and-save}). 
-@item C-c C-v M-C-s
-@kindex C-c C-v M-C-s (Summary)
-@findex gnus-uu-marked-shar-and-view
-@kindex C-c C-v M-C-s (Summary)
-@findex gnus-uu-marked-shar-and-view
-Unshar and view the marked articles
-(@code{gnus-uu-marked-shar-and-view}). 
-@item C-c C-v M-s
-@kindex C-c C-v M-s (Summary)
-@findex gnus-uu-marked-shar-and-view
-@kindex C-c C-v M-s (Summary)
-@findex gnus-uu-marked-shar-and-view
-Unshar and save the marked articles
-(@code{gnus-uu-marked-shar-and-view}). 
-@end table
-
-@node Decoding With Other Decoders
-@subsubsection Decoding With Other Decoders
-
-These commands are entry points to all the decoding methods Gnus knows -
-uudecode, unshar, unbinhex and save.  You will be prompted for what
-method you want to employ.
+Remember that these all react to the presence of articles marked with
+the process mark.  If, for instance, you'd like to uncode and save an
+entire newsgroup, you'd typically do @kbd{M p a}
+(@code{gnus-uu-mark-all}) and then @kbd{X U} (@code{gnus-uu-decode-uu}).
 
-@table @kbd
-@item C-c C-v C-m
-@kindex C-c C-v C-m (Summary)
-@findex gnus-uu-multi-decode-and-view
-Decode (by some method) and view the series of articles that the current
-article is a part of (@code{gnus-uu-multi-decode-and-view}).
-@item C-c C-v m
-@kindex C-c C-v m (Summary)
-@findex gnus-uu-multi-decode-and-save
-Decode (by some method) and save the series of articles that the current
-article is a part of (@code{gnus-uu-multi-decode-and-save}).
-@item C-c C-v M-C-m
-@kindex C-c C-v M-C-m (Summary)
-@findex gnus-uu-marked-multi-decode-and-view
-Decode (by some method) and view the marked articles
-(@code{gnus-uu-marked-multi-decode-and-view}). 
-@item C-c C-v M-m
-@kindex C-c C-v M-m (Summary)
-@findex gnus-uu-marked-multi-decode-and-view
-Decode (by some method) and save the marked articles
-(@code{gnus-uu-marked-multi-decode-and-view}). 
-@item C-c C-v C-j
-@kindex C-c C-v C-j (Summary)
-@findex gnus-uu-threaded-multi-decode-and-view
-Decode (by some method) and view all articles in the current thread
-(@code{gnus-uu-threaded-multi-decode-and-view}). 
-@item C-c C-v C-j
-@kindex C-c C-v C-j (Summary)
-@findex gnus-uu-threaded-multi-decode-and-view
-Decode (by some method) and save all articles in the current thread
-(@code{gnus-uu-threaded-multi-decode-and-view}). 
-@end table
-
-@node Setting the Process Mark
-@subsection Setting the Process Mark
-
-The process mark is used by other parts of Gnus, not just the `gnus-uu'
-package.  However, this is where it is most useful, so it adds some
-further methods for setting the mark.
+All this is very much different from how gnus-uu worked with @sc{GNUS
+4.1}, where you had explicit keystrokes for everything under the sun.
+This version of gnus-uu generally assumes that you either mark articles
+in some way (@pxref{Setting Process Marks}) and then press @kbd{X u}.
 
-@table @kbd
-@item C-c C-v C-r
-@kindex C-c C-v C-r (Summary)
-@findex gnus-uu-mark-by-regexp
-Mark articles by a regular expression (@code{gnus-uu-mark-by-regexp}). 
-@item C-c C-v r
-@kindex C-c C-v r (Summary)
-@findex gnus-uu-mark-region
-Mark all articles between point and mark (@code{gnus-uu-mark-region}). 
-@item C-c C-v t
-@kindex C-c C-v t (Summary)
-@findex gnus-uu-mark-thread
-Mark all articles downward in the current thread
-(@code{gnus-uu-mark-thread}). 
-@end table
+Note: When trying to decode articles that have names matching
+@samp{[Cc][Ii][Nn][Dd][Yy][0-9]+.\\(gif\\|jpg\\)}
+(@code{gnus-uu-notify-files}), gnus-uu will automatically post an
+article on @samp{comp.unix.wizards} saying that you have just viewed the
+file in question.  This feature can't be turned off.
 
-@node Other Related Commands
-@subsection Other Related Commands
+@node Shared Articles
+@subsection Shared Articles
+@cindex unshar
+@cindex shared articles
 
-@table @key
-@item C-c C-v f
-@kindex C-c C-v f (Summary)
-@findex gnus-uu-digest-and-forward
-Digest and forward all articles that are part of a series
-(@code{gnus-uu-digest-and-forward}). 
-@item C-c C-v M-f
-@kindex C-c C-v M-f (Summary)
-@findex gnus-uu-marked-digest-and-forward
-Digest and forward all marked articles
-(@code{gnus-uu-marked-digest-and-forward}).
-@item C-c C-v C-i
-@kindex C-c C-v C-i (Summary)
-@findex gnus-uu-toggle-interactive-view
-Instead of having windows popping up automatically, it can be handy to
-view files interactivly, especially when viewing archives
-(@code{gnus-uu-toggle-interactive-view}).
-@item C-c C-v C-t
-@kindex C-c C-v C-t (Summary)
-@findex gnus-uu
-Toggle any of the most important @code{gnus-uu} variables
-(@code{gnus-uu-toggle-any-variable}).
-@item C-c C-v C-l
-@kindex C-c C-v C-l (Summary)
-@findex gnus-uu-edit-begin-line
-Edit the @samp{begin} line of an uuencoded article, if any
-(@code{gnus-uu-edit-begin-line}).  
-@item C-c C-v p
-@kindex C-c C-v p (Summary)
-@findex gnus-uu-post-news
-Uuencode and post an file.  If the file is large, it will be split into a
-series of articles that will be posted (@code{gnus-uu-post-news}).
+@table @kbd
+@item X s
+@kindex X s (Summary)
+@findex gnus-uu-decode-unshar
+Unshars the current series (@code{gnus-uu-decode-unshar}).
+@item X S
+@kindex X S (Summary)
+@findex gnus-uu-decode-unshar-and-save
+Unshars and saves the current series (@code{gnus-uu-decode-unshar-and-save}).
+@item X v s
+@kindex X v s (Summary)
+@findex gnus-uu-decode-unshar-view
+Unshars and views the current series (@code{gnus-uu-decode-unshar-view}).
+@item X v S
+@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}). 
 @end table
 
-@node Viewing Files
-@subsection Viewing Files
-
-When using the view commands, @code{gnus-uu-decode-and-view} for
-instance, Gnus will (normally, see below) try to view the file according
-to the rules given in @code{gnus-uu-default-view-rules} and
-@code{gnus-uu-user-view-rules}.  If it recognizes the file, it will
-display it immediately.  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 uncompress and detar 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.
-
-If the view command doesn't recognise the file type, or can't view it
-because you don't have the viewer, or can't view *any* of the files in
-the archive, the user will be asked if she wishes to have the file saved
-somewhere.  Note that if the decoded file is an archive, and Gnus
-manages to view some of the files in the archive, it won't tell the user
-that there were some files that were unviewable.  Try interactive view
-for a different approach.
-
 @node Decoding Variables
 @subsection Decoding Variables
 
@@ -2353,15 +3189,16 @@ Adjective, not verb.
 
 @node Rule Variables
 @subsubsection Rule Variables
+@cindex rule variables
 
 Gnus uses @dfn{rule} variables to decide how to view a file.  All these
 variables are on the form
   
-@example
+@lisp
       (list '(regexp1 command2)
             '(regexp2 command2)
             ...)
-@end example
+@end lisp
 
 @table @code
 @item gnus-uu-user-view-rules
@@ -2369,22 +3206,14 @@ variables are on the form
 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
 say something like:
-@example
+@lisp
        (setq gnus-uu-user-view-rules
          (list '(\"\\\\.au$\" \"sox %s -t .aiff > /dev/audio\")))
-@end example
+@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
 user and default view rules.
-@item gnus-uu-user-interactive-view-rules
-@vindex gnus-uu-user-interactive-view-rules
-This is the variable used instead of @code{gnus-uu-user-view-rules}
-when in interactive mode.
-@item gnus-uu-user-interactive-view-rules-end
-@vindex gnus-uu-user-interactive-view-rules-end
-This variable is used instead of @code{gnus-uu-user-view-rules-end} when
-in interactive mode.
 @item gnus-uu-user-archive-rules
 @vindex gnus-uu-user-archive-rules
 This variable can be used to say what comamnds should be used to unpack
@@ -2411,81 +3240,58 @@ Where gnus-uu does its work.
 
 @item gnus-uu-do-not-unpack-archives
 @vindex gnus-uu-do-not-unpack-archives
-Non-nil means that gnus-uu won't peek inside archives looking for files
-to dispay.
+Non-@code{nil} means that gnus-uu won't peek inside archives looking for
+files to dispay.
 
 @item gnus-uu-view-and-save
 @vindex gnus-uu-view-and-save
-Non-nil means that the user will always be asked to save a file after
-viewing it.
-
-@item gnus-uu-asynchronous
-@vindex gnus-uu-asynchronous
-Non-nil means that files will be viewed asynchronously.  This can be
-useful if you're viewing long @file{.mod} files, for instance, which
-often takes several minutes.  Note, however, that since gnus-uu doesn't
-ask, and if you are viewing an archive with lots of viewable files,
-you'll get them all up more or less at once, which can be confusing, to
-say the least.  To get gnus-uu to ask you before viewing a file, set the
-@code{gnus-uu-ask-before-view} variable.
-
-@item gnus-uu-ask-before-view
-@vindex gnus-uu-ask-before-view
-Non-nil means that gnus-uu will ask you before viewing each file.
+Non-@code{nil} means that the user will always be asked to save a file
+after viewing it.
 
 @item gnus-uu-ignore-default-view-rules
 @vindex gnus-uu-ignore-default-view-rules
-Non-nil means that gnus-uu will ignore the default viewing rules.
+Non-@code{nil} means that gnus-uu will ignore the default viewing rules.
 
 @item gnus-uu-ignore-default-archive-rules
 @vindex gnus-uu-ignore-default-archive-rules
-Non-nil means that gnus-uu will ignore the default archive unpacking
-commands.
+Non-@code{nil} means that gnus-uu will ignore the default archive
+unpacking commands.
 
 @item gnus-uu-kill-carriage-return
 @vindex gnus-uu-kill-carriage-return
-Non-nil means that gnus-uu will strip all carriage returns from
+Non-@code{nil} means that gnus-uu will strip all carriage returns from
 articles.
 
 @item gnus-uu-unmark-articles-not-decoded
 @vindex gnus-uu-unmark-articles-not-decoded
-Non-nil means that gnus-uu will mark articles that were unsuccessfully
-decoded as unread.
-
-@item gnus-uu-output-window-height
-@vindex gnus-uu-output-window-height
-This variable says how tall the output buffer window is to be when using
-interactive view mode.
+Non-@code{nil} means that gnus-uu will mark articles that were
+unsuccessfully decoded as unread.
 
 @item gnus-uu-correct-stripped-uucode
 @vindex gnus-uu-correct-stripped-uucode
-Non-nil means that gnus-uu will *try* to fix uuencoded files that have
-had traling spaces deleted.
-
-@item gnus-uu-use-interactive-view
-@vindex gnus-uu-use-interactive-view
-Non-nil means that gnus-uu will use interactive viewing mode.
+Non-@code{nil} means that gnus-uu will *try* to fix uuencoded files that
+have had traling spaces deleted.
 
 @item gnus-uu-view-with-metamail
 @vindex gnus-uu-view-with-metamail
-Non-nil means that gnus-uu will ignore the viewing commands defined by
-the rule variables and just fudge a MIME content type based on the file
-name.  The result will be fed to metamail for viewing.
+Non-@code{nil} means that gnus-uu will ignore the viewing commands
+defined by the rule variables and just fudge a MIME content type based
+on the file name.  The result will be fed to metamail for viewing.
 
 @item gnus-uu-save-in-digest
 @vindex gnus-uu-save-in-digest
-Non-nil means that gnus-uu, when asked to save without decoding, will
-save in digests.  If this variable is nil, gnus-uu will just save
-everything in a file without any embellishments.  The digesting almost
-conforms to RFC1153 - no easy way to specify any meaningful volume and
-issue numbers were found, so I simply dropped them.
+Non-@code{nil} means that gnus-uu, when asked to save without decoding,
+will save in digests.  If this variable is @code{nil}, gnus-uu will just
+save everything in a file without any embellishments.  The digesting
+almost conforms to RFC1153 - no easy way to specify any meaningful
+volume and issue numbers were found, so I simply dropped them.
 
 @item gnus-uu-post-include-before-composing
 @vindex gnus-uu-post-include-before-composing
-Non-nil means that gnus-uu will ask for a file to encode before you
-compose the article.  If this variable is t, you can either include an
-encoded file with @key{C-c C-i} or have one included for you when you
-post the article.
+Non-@code{nil} means that gnus-uu will ask for a file to encode before
+you compose the article.  If this variable is @code{t}, you can either
+include an encoded file with @key{C-c C-i} or have one included for you
+when you post the article.
 
 @item gnus-uu-post-length
 @vindex gnus-uu-post-length
@@ -2494,83 +3300,155 @@ many articles it takes to post the entire file.
 
 @item gnus-uu-post-threaded
 @vindex gnus-uu-post-threaded
-Non-nil means that gnus-uu will post the encoded file in a thread.  This
-may not be smart, as no other decoder I have seen are able to follow
-threads when collecting uuencoded articles.  (Well, I have seen one
-package that does that - gnus-uu, but somehow, I don't think that
-counts...) Default is nil.
+Non-@code{nil} means that gnus-uu will post the encoded file in a
+thread.  This may not be smart, as no other decoder I have seen are able
+to follow threads when collecting uuencoded articles.  (Well, I have
+seen one package that does that - gnus-uu, but somehow, I don't think
+that counts...) Default is @code{nil}.
 
 @item gnus-uu-post-separate-description
 @vindex gnus-uu-post-separate-description
-Non-nil means that the description will be posted in a separate article.
-The first article will typically be numbered (0/x).  If this variable is
-nil, the description the user enters will be included at the beginning
-of the first article, which will be numbered (1/x).  Default is t.
+Non-@code{nil} means that the description will be posted in a separate
+article.  The first article will typically be numbered (0/x).  If this
+variable is @code{nil}, the description the user enters will be included
+at the beginning of the first article, which will be numbered (1/x).
+Default is @code{t}.
 
 @end table
 
+@node Viewing Files
+@subsection Viewing Files
+@cindex vieving files
+@cindex pseudo-articles
+
+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
+uncompress and detar 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
+extracted file into the summary buffer.  If you go to these "articles",
+the user will be prompted for a command to run (usually Gnus will make a
+suggestion), and then the command will be run.
+
+@vindex gnus-view-pseudo-asynchronously
+If @code{gnus-view-pseudo-asynchronously} is @code{nil}, Emacs will wait
+until the viewing is done before proceeding.
+
+@vindex gnus-view-pseudos
+If @code{gnus-view-pseudos} is @code{automatic}, Gnus will not insert
+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.
+
+
 @node Various Article Stuff 
 @section Various Article Stuff 
 
 @table @kbd
-@item w
-@kindex w (Summary)
+@item w
+@kindex w (Summary)
 @findex gnus-summary-stop-page-breaking
 Remove page breaking from the current article
 (@code{gnus-summary-stop-page-breaking}). 
-@item C-c C-r
-@kindex C-c C-r (Summary)
+@item A s 
+@item A s (Summary)
+@findex gnus-summary-isearch-article
+Perform an isearch in the article buffer
+(@code{gnus-summary-isearch-article}). 
+@item A c
+@kindex A c (Summary)
 @findex gnus-summary-caesar-message
 Do a Caesar rotate (rot13) on the article buffer
 (@code{gnus-summary-caesar-message}). 
-@item g
-@kindex g (Summary)
+@item g
+@kindex g (Summary)
 @findex gnus-summary-show-article
 Select the current article (@code{gnus-summary-show-article}).
-@item t
-@kindex t (Summary)
+@item t
+@kindex t (Summary)
 @findex gnus-summary-toggle-header
 Toggle whether to display all headers in the article buffer
 (@code{gnus-summary-toggle-header}). 
-@item M-t
-@kindex M-t (Summary)
+@item A m
+@kindex A m (Summary)
 @findex gnus-summary-toggle-mime
 Toggle whether to run the article through MIME before displaying
 (@code{gnus-summary-toggle-mime}). 
-@item |
-@kindex | (Summary)
+@item |
+@kindex | (Summary)
 @findex gnus-summary-pipe-output
-Pipe the current article through a filter
+Pipe the current article to a process
 (@code{gnus-summary-pipe-output}). 
 @end table
 
+There's a battery of commands for washing the article buffer:
+
+@table @kbd
+@item A h h
+@kindex A h h (Summary)
+@findex gnus-article-hide-headers
+Hide headers (@code{gnus-article-hide-headers}).
+@item A h s
+@kindex A h s (Summary)
+@findex gnus-article-hide-signature
+Hide signature (@code{gnus-article-hide-signature}).
+@item A h c
+@kindex A h c (Summary)
+@findex gnus-article-hide-citation
+Hide citation (@code{gnus-article-hide-citation}).
+@item A h o
+@kindex A h o (Summary)
+@findex gnus-article-treat-overstrike
+Treat overstrike (@code{gnus-article-treat-overstrike}).
+@item A h w
+@kindex A h w (Summary)
+@findex gnus-article-word-wrap
+Do word wrap (@code{gnus-article-word-wrap}).
+@item A h d
+@kindex A h d (Summary)
+@findex gnus-article-remove-cr
+Remove CR (@code{gnus-article-remove-cr}).
+@item A h q
+@kindex A h q (Summary)
+@findex gnus-article-de-quoted-unreadable
+Treat quoted-printable (@code{gnus-article-de-quoted-unreadable}).
+@end table
+
+
 @node Summary Sorting
 @section Summary Sorting
+@cindex summary sorting
 
 You can have the summary buffer sorted in various ways, even though I
 can't really se why you'd want that.
 
 @table @kbd
-@item C-c C-s C-n
-@kindex C-c C-s C-n (Summary)
+@item V s n
+@kindex V s n (Summary)
 @findex gnus-summary-sort-by-number
 Sort by article number (@code{gnus-summary-sort-by-number}).
-@item C-c C-s C-a
-@kindex C-c C-s C-a (Summary)
+@item V s a
+@kindex V s a (Summary)
 @findex gnus-summary-sort-by-author
 Sort by author (@code{gnus-summary-sort-by-author}).
-@item C-c C-s C-s
-@kindex C-c C-s C-s (Summary)
+@item V s s
+@kindex V s s (Summary)
 @findex gnus-summary-sort-by-subject
 Sort by subject (@code{gnus-summary-sort-by-subject}).
-@item C-c C-s C-d
-@kindex C-c C-s C-d (Summary)
+@item V s d
+@kindex V s d (Summary)
 @findex gnus-summary-sort-by-date
 Sort by date (@code{gnus-summary-sort-by-date}).
 @end table
 
 @node Finding the Parent
 @section Finding the Parent
+@cindex parent articles
+@cindex refering articles
 
 @findex gnus-summary-refer-parent-article
 @kindex ^ (Summary)
@@ -2579,7 +3457,7 @@ displayed in the article buffer, you might still be able to.  That is,
 if the current group is fetched by NNTP, the parent hasn't expired and
 the References in the current article are not mangled, you can just
 press @kbd{^} (@code{gnus-summary-refer-parent-article}).  If everything
-goes well, you'll get the parent. If the parent is already displayed in
+goes well, you'll get the parent.  If the parent is already displayed in
 the summary buffer, point will just move to this article.
 
 @findex gnus-summary-refer-article
@@ -2590,168 +3468,596 @@ will ask you for a message-id, which is one of those long thingies that
 look something like @samp{<38o6up$6f2@@hymir.ifi.uio.no>}.  You have to
 get it all exactly right.
 
+@vindex gnus-refer-article-method
+If the group you are reading is located on a backend that does not
+support fetching by Message-ID very well (like @code{nnspool}), you can
+set @code{gnus-refer-article-method} to an NNTP method.  It would,
+perhaps, be best if the NNTP server you consult is the same as the one
+that keeps the spool you are erading from updated, but that's not really
+necessary. 
+
 @node Score Files
 @section Score Files
+@cindex score files
 
-Other people call them @dfn{kill files}, but we here at (ding) Gnus
-Towers likes scoring better than killing, so we've changed the
-name. We've also changed what they do, so sit up straight and pay
+Other people use @dfn{kill files}, but we here at (ding) 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}).
-This score may be raised or lowered either interactively or by the score
-files. Articles that have a score lower than
-@code{gnus-summary-mark-below} are marked as read. 
-
-If a @dfn{score file} for the current group exists, Gnus will read it
-after generating the summary buffer.
+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.
 
-The score files are files that may contain, in general, any elisp
-functions.  However, it is most common just to put functions that either
-raises or lowers the score of articles based on their headers in those
-files.  Hence the name.
+Gnus will read any @dfn{score files} that apply to the current group
+before generating the summary buffer.
 
 There are several commands reachable from the summary buffer that
 inserts commands for scoring articles based on the current article.  You
-can, for instance, ask Gnus to lower or raise the score of all articles
-with a certain subject.
+can, for instance, ask Gnus to lower or increase the score of all
+articles with a certain subject.
+
+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 simple score commands to the score file.
-* Score Mode::               A mode for editing the score file.
+* Summary Score Commands::   Adding score commands to the score file.
 * 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.
+* Scoring Tips::             How to score effectively.
+* Global Score Files::       Earth-spanning, ear-splitting score files.
 @end menu
 
 @node Summary Score Commands
 @subsection Summary Score Commands
+@cindex score commands
+
+General score commands don't actually change score files: 
+
+@table @kbd
+@item V S s
+@kindex V S s (Summary)
+@findex gnus-summary-set-score
+Set the score of the current article (@code{gnus-summary-set-score}).  
+@item I C-i
+@kindex I C-i (Summary)
+@findex gnus-summary-raise-score
+Increase the score of the current article
+(@code{gnus-summary-raise-score}).
+@item L C-l
+@kindex L C-l (Summary)
+@findex gnus-summary-lower-score
+Lower the score of the current article
+(@code{gnus-summary-lower-score}). 
+@item V S c
+@kindex V S c (Summary)
+@findex gnus-score-change-score-file
+Make a different score file the current
+(@code{gnus-score-change-score-file}). 
+@item V S e
+@kindex V S e (Summary)
+@findex gnus-score-edit-file
+Edit the current score file (@code{gnus-score-edit-file}).  You will be
+popped into a @code{gnus-score-mode} buffer (@pxref{Score File
+Editing}). 
+@end table
+
+The rest of these commands modify the local score file.
 
 @table @kbd
-@item C-c C-k C-s
-@kindex C-c C-k C-s (Summary)
-@findex gnus-kill-file-kill-by-subject
-Kill all articles with the current subject
-(@code{gnus-kill-file-kill-by-subject}). 
-@item C-c C-k C-a
-@kindex C-c C-k C-a (Summary)
-@findex gnus-kill-file-kill-by-author
-Kill all articles from the current author
-(@code{gnus-kill-file-kill-by-author}). 
-@item C-c C-k C-t
-@kindex C-c C-k C-t (Summary)
-@findex gnus-kill-file-kill-by-thread
-Kill all articles in the current subthread
-(@code{gnus-kill-file-kill-by-thread}). 
-@item C-c C-k C-o
-@kindex C-c C-k C-o (Summary)
-@findex gnus-kill-file-kill-by-organization
-Kill all articles from the current organization
-(@code{gnus-kill-file-kill-by-organization}). 
-@item C-c C-k C-x
-@kindex C-c C-k C-x (Summary)
-@findex gnus-kill-file-kill-by-xref
-Kill all articles that have similar Xrefs to the current article
-(@code{gnus-kill-file-kill-by-xref}).  This is one way to get rid of
-cross-posts. 
-@end table
-
-@node Score Mode
-@subsection Score Mode
-
-To enter either the global or local score file, you can use the
-following keystrokes in the summary buffer:
+@item V S m
+@kindex V S 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 S E
+@kindex V S E (Summary)
+@findex gnus-score-set-expunge-below
+Expunge all articles with a score below the default score (or the
+numeric prefix) (@code{gnus-score-set-expunge-below}).
+@end table
+
+Commands for increasing score:
 
 @table @kbd
-@item M-k
-@kindex M-k (Summary)
-@findex gnus-summary-edit-local-kill
-Edit the kill file for the current group
-(@code{gnus-summary-edit-local-kill}). 
-@item M-K
-@kindex M-K (Summary)
-@findex gnus-summary-edit-global-kill
-Edit the global kill file (@code{gnus-summary-edit-global-kill}). 
+@item I s t
+@kindex I s t (Summary)
+@findex gnus-summary-temporarily-raise-by-subject
+Increase the current subject temporarily
+(@code{gnus-summary-temporarily-raise-by-subject}).
+@item I s p
+@kindex I s p (Summary)
+@findex gnus-summary-raise-by-subject
+Increase the current subject permanently
+(@code{gnus-summary-raise-by-subject}).
+@item I a t
+@kindex I a t (Summary)
+@findex gnus-summary-temporarily-raise-by-author
+Increase the current author temporarily
+(@code{gnus-summary-temporarily-raise-by-author}).
+@item I a p
+@kindex I a p (Summary)
+@findex gnus-summary-raise-by-author
+Increase the current author permanently
+(@code{gnus-summary-raise-by-author}).
+@item I i t
+@kindex I i t (Summary)
+@findex gnus-summary-temporarily-raise-by-id
+Increase the current message-id temporarily
+(@code{gnus-summary-temporarily-raise-by-id}).
+@item I i p
+@kindex I i p (Summary)
+@findex gnus-summary-raise-by-id
+Increase the current message-id permanently
+(@code{gnus-summary-raise-by-id}).
+@item I t t
+@kindex I t t (Summary)
+@findex gnus-summary-temporarily-raise-by-thread
+Increase the current thread temporarily
+(@code{gnus-summary-temporarily-raise-by-thread}).
+@item I t p
+@kindex I t p (Summary)
+@findex gnus-summary-raise-by-subject
+Increase the current thread permanently
+(@code{gnus-summary-raise-by-subject}).
+@item I x t
+@kindex I x t (Summary)
+@findex gnus-summary-temporarily-raise-by-xref
+Increase the current xref temporarily
+(@code{gnus-summary-temporarily-raise-by-xref}).
+@item I x p
+@kindex I x p (Summary)
+@findex gnus-summary-raise-by-xref
+Increase the current xref permanently
+(@code{gnus-summary-raise-by-xref}).
+@item I f t
+@kindex I f t (Summary)
+@findex gnus-summary-temporarily-raise-followups-to-author
+Increase followups to the current author temporarily
+(@code{gnus-summary-temporarily-raise-followups-to-author}).
+@item I f p
+@kindex I f p (Summary)
+@findex gnus-summary-raise-followups-to-author
+Increase followups to the current author permanently
+(@code{gnus-summary-raise-followups-to-author}).
+@end table
+
+Commands for lowering score:
+
+@table @kbd
+@item L s t
+@kindex L s t (Summary)
+@findex gnus-summary-temporarily-lower-by-subject
+Lower the current subject temporarily
+(@code{gnus-summary-temporarily-lower-by-subject}).
+@item L s p
+@kindex L s p (Summary)
+@findex gnus-summary-lower-by-subject
+Lower the current subject permanently
+(@code{gnus-summary-lower-by-subject}).
+@item L a t
+@kindex L a t (Summary)
+@findex gnus-summary-temporarily-lower-by-author
+Lower the current author temporarily
+(@code{gnus-summary-temporarily-lower-by-author}).
+@item L a p
+@kindex L a p (Summary)
+@findex gnus-summary-lower-by-author
+Lower the current author permanently
+(@code{gnus-summary-lower-by-author}).
+@item L i t
+@kindex L i t (Summary)
+@findex gnus-summary-temporarily-lower-by-id
+Lower the current message-id temporarily
+(@code{gnus-summary-temporarily-lower-by-id}).
+@item L a p
+@kindex L a p (Summary)
+@findex gnus-summary-lower-by-id
+Lower the current message-id permanently
+(@code{gnus-summary-lower-by-id}).
+@item L t t
+@kindex L t t (Summary)
+@findex gnus-summary-temporarily-lower-by-thread
+Lower the current thread temporarily
+(@code{gnus-summary-temporarily-lower-by-thread}).
+@item L t p
+@kindex L t p (Summary)
+@findex gnus-summary-lower-by-subject
+Lower the current thread permanently
+(@code{gnus-summary-lower-by-subject}).
+@item L x t
+@kindex L x t (Summary)
+@findex gnus-summary-temporarily-lower-by-xref
+Lower the current xref temporarily
+(@code{gnus-summary-temporarily-lower-by-xref}).
+@item L x p
+@kindex L x p (Summary)
+@findex gnus-summary-lower-by-xref
+Lower the current xref permanently
+(@code{gnus-summary-lower-by-xref}).
+@item L f t
+@kindex L f t (Summary)
+@findex gnus-summary-temporarily-lower-followups-to-author
+Lower followups to the current author temporarily
+(@code{gnus-summary-temporarily-lower-followups-to-author}).
+@item L f p
+@kindex L f p (Summary)
+@findex gnus-summary-lower-followups-to-author
+Lower followups to the current author permanently
+(@code{gnus-summary-lower-followups-to-author}).
 @end table
 
 @node Score Variables
 @subsection Score Variables
+@cindex score variables
 
 @table @code
 @item gnus-kill-killed
 @vindex gnus-kill-killed
-If this variable is 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 t to do that.
-@item gnus-apply-kill-hook
-@vindex gnus-apply-kill-hook
-This hook is called to do the actual article killing.  This hook may do
-anything, of course, but it should call the @code{gnus-apply-kill-file}
-function, or some equivalent function, to do the killing.
+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.
 @item gnus-kill-files-directory
 @vindex gnus-kill-files-directory
 All kill files will be stored in this directory, which is initialized
 from the @samp{SAVEDIR} environment variable by default.
-@item gnus-kill-file-name
-@vindex gnus-kill-file-name
-This variable is a string that will be appended to group names to
-make a kill file name.  The default is @samp{KILL}.
+@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 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 that successive adaptive changes
+to overwrite manually entered data.
+@item gnus-summary-default-score
+@vindex gnus-summary-default-score
+Default score of an article, which is 0 by default.
+@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 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 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. 
+
+Predefined functions available are:
+@table @code
+@item gnus-score-find-single
+@findex gnus-score-find-single
+Only apply the group's own score file.
+@item gnus-score-find-bnews
+@findex gnus-score-find-bnews
+Apply all score files that match, using bnews syntax.  For instance, if
+the current group is @samp{gnu.emacs.gnus}, @samp{gnu.all.SCORE},
+@samp{all.emacs.all.SCORE} and @samp{not.alt.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.
+@item gnus-score-find-hierarchical
+@findex gnus-score-find-hierarchical
+Apply all score files from all the parent groups.
+@end table
+@item gnus-kill-expiry-days
+@vindex gnus-kill-expiry-days
+This variable says how many days should pass before an unused score file
+entry should be expired.  The default is 7.
+@end table
+
+@node Score File Format
+@subsection Score File Format
+@cindex score file format
+
+A score file is an emacs-lisp file that normally contains just a single
+form.  Casual users are not expected to edit these files, everthing can
+be changed from the summary buffer.
+
+Anyway, if you'd like to dig into it yourself, here's an example:
+
+@lisp
+(("from"
+  ("Lars Ingebrigtsen" -10000)
+  ("Per Abrahamsen")
+  ("larsi\\|lmi" -50000 nil r))
+ ("subject"
+  ("Ding is Badd" nil 728373))
+ ("xref"
+  ("alt.politics" -1000 728372 s))
+ (mark 0)
+ (expunge -1000)
+ (mark-and-expunge -10)
+ (read-only t)
+ (files "/hom/larsi/News/gnu.SCORE")
+ (eval (ding)))
+@end lisp
+
+This example demonstrates absolutely everything about a score file. 
+
+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 legal syntactically, if not semantically.
+
+Six keys are supported by this alist:
+
+@table @code
+@item STRING
+If the key is a string, it is a header name to perform the scoring on.
+Following this key is a random number of element score entries, where
+each score entry have one to four elements.  
+@enumerate
+@item 
+The first element is always a string - the @dfn{match element}.
+@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.  If this element is not present, the
+@code{gnus-score-interactive-default-score} number will be used instead.
+@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 provided a
+match, which provides a mechanism for expiring the score entries.  It
+this element is not present, the score entry is premanent.  The date is
+represented by the number of days since December 31, 1 CE.
+@item 
+If the fourth element is present, it should be a symbol - the @dfn{type
+element}.  Currently supported are the @code{r} (regexp) and @code{s}
+(substring) types.  If this element is not present, Gnus will assume
+that substring matching should be used.
+@end enumerate
+
+@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.
+@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.
+@item files
+The value of this entry should 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.
+@item eval
+The value of this entry will be @code{eval}el.  This element will be
+ignored when handling global score files. 
+@item read-only
+Read-only score files will not be updated or saved.  Global score files
+should feature this atom (@pxref{Global Score Files}).
+@end table
+
+@node Score File Editing
+@subsection 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 emacs-lisp mode, with these additional
+commands:
+
+@table @kbd
+@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}). 
+@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.
+@end table
+
+@node Scoring Tips
+@subsection Scoring Tips
+@cindex scoring tips
+
+@table . 
+@item Crossposts
+If you want to lower the score of crossposts, the line to match on is
+the Xref header.  
+@lisp
+("xref" (" talk.politics.misc:" -1000))
+@end lisp
+@item Multiple crossposts
+If you want to lower the score of articles that have been crossposted to
+more than, say, 3 groups:
+@lisp
+("xref" (" +[^ ]+:[0-9]+ +[^ ]+:[0-9]+ +[^ ]+:[0-9]+" -1000 nil r))
+@end lisp
 @end table
 
+@node Global Score Files
+@subsection Global Score Files
+@cindex global score files
+
+Sure, other newsreaders have "global kill files".  These are usually
+nothing more than a single kill file that applies to all groups, stored
+under 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!
+
+@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}.  One entry for each score file, or each
+score file directory.  Gnus will decide by itself what score files are
+applicable to which group.
+
+Say you want to use the single score file
+@file{/ftp@@ftp.ifi.uio.no:/pub/larsi/ding/score/soc.motss.SCORE} and all
+score files in the @file{/ftp@@ftp.some-where:/pub/score} directory.  
+
+@lisp
+(setq gnus-global-score-files
+      '("/ftp@@ftp.ifi.uio.no:/pub/larsi/ding/score/soc.motss.SCORE"
+        "/ftp@@ftp.some-where:/pub/score/"))
+@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.
+
+Note that, at present, using this option will slow down group entry
+somewhat.  (That is - a lot.)
+
+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: 
+
+@itemize @bullet
+@item 
+Articles that are heavily crossposted are probably junk. 
+@item
+To lower a single inappropriate article, lower by 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 existance.
+@item
+Set the @code{mark} and @code{expunge} atoms to obliterate the nastiest
+articles completely.
+@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
+
+... I wonder whether other newsreaders will support global score files
+in the future.  *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 Mail Group Commands
 @section Mail Group Commands
+@cindex mail group commands
+
+Some commands only make sense in mail groups.  If these commands are
+illegal in the current group, they will raise a hell and let you know.
 
-Some commands only make sense in mail groups. 
+All these commands (except the expiry and edit commands) use the
+process/prefix convention (@pxref{Process/Prefix}).
 
 @table @kbd
-@item M-C-x
-@kindex M-C-x (Summary)
+@item V m e
+@kindex V m e (Summary)
 @findex gnus-summary-expire-articles
 Expire all expirable articles in the group
 (@code{gnus-summary-expire-articles}).
-@item M-DEL
-@kindex M-DEL (Summary)
+@item V m DEL
+@kindex V m DEL (Summary)
 @findex gnus-summary-delete-articles
-Delete the mail article. This is "delete" as in "delete it from your
+Delete the mail article.  This is "delete" as in "delete it from your
 disk forever and ever, never to return again." Use with caution.
 (@code{gnus-summary-delete-article}).
-@item M-m
-@kindex M-m (Summary)
+@item V m m
+@kindex V m m (Summary)
 @findex gnus-summary-move-article
 Move the article from one mail group to another
 (@code{gnus-summary-move-article}). 
-@item M-C-m
-@kindex M-C-m (Summary)
+@item V m c
+@kindex V m c (Summary)
+@findex gnus-summary-copy-article
+Copy the article from one group (mail group or not) to a mail group
+(@code{gnus-summary-copy-article}).
+@item V m r
+@kindex V m r (Summary)
 @findex gnus-summary-respool-article
 Respool the mail article (@code{gnus-summary-move-article}).
+@item V m w
+@item e
+@kindex V m w (Summary)
+@kindex e (Summary)
+@findex gnus-summary-edit-article
+@kindex C-c C-c (Article)
+Edit the current article (@code{gnus-summary-edit-article}).  Type
+@kbd{C-c C-c} (@kbd{gnus-summary-edit-article-done}) to finish editing
+and make the changes permanent.
 @end table
 
 @node Various Summary Stuff
 @section Various Summary Stuff
 
 @table @kbd
+@item V D
+@kindex V D (Summary)
+@findex gnus-summary-enter-digest-group
+If the current article is a digest, you might use this command to enter
+you into a group based onthe current digest to ease reading
+(@code{gnus-summary-enter-digest-group}).  @xref{nndigest}.
+@item V f
+@kindex V 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. ange-ftp will be used for fetching the file.
 @item &
 @kindex & (Summary)
 @findex gnus-summary-expand-window
 This command will prompt you for a header field, a regular expression to
 be matched this field, and a command to be executed if the match is
 made. 
-@item =
-@kindex = (Summary)
+@item V C-s
+@kindex V C-s (Summary)
+@findex gnus-summary-search-article-forward
+Search through all subsequent articles for a regexp
+(@code{gnus-summary-search-article-forward}). 
+@item V C-r
+@kindex V C-r (Summary)
+@findex gnus-summary-search-article-backward
+Search through all previous articles for a regexp
+(@code{gnus-summary-search-article-backward}). 
+@item V T
+@kindex V T (Summary)
+@findex gnus-summary-toggle-truncation
+Toggle truncation of summary lines (@code{gnus-summary-toggle-truncation}).
+@item V e
+@kindex V e (Summary)
 @findex gnus-summary-expand-window
-Delete all other windows (@code{gnus-summary-expand-window}).
-@item C-x C-s
-@kindex C-x C-s (Summary)
+Expand the summary buffer window (@code{gnus-summary-expand-window}).
+@item V S
+@kindex V S (Summary)
 @findex gnus-summary-reselect-current-group
 Exit this group, and then enter it again
 (@code{gnus-summary-reselect-current-group}).
-@item C-c C-d
-@kindex C-c C-d (Summary)
+@item d
+@kindex d (Summary)
 @findex gnus-summary-describe-group
 Give a brief description of the current group
-(@code{gnus-summary-describe-group}).
+(@code{gnus-summary-describe-group}).  If given a prefix, force reading
+new description from the server. 
+@item V g
 @item M-g
+@kindex V g (Summary)
 @kindex M-g (Summary)
 @findex gnus-summary-rescan-group
 Exit group, check for new articles in the group, and select the group
@@ -2760,13 +4066,13 @@ Exit group, check for new articles in the group, and select the group
 @kindex V (Summary)
 @findex gnus-version
 Display the Gnus version numbers (@code{gnus-version}).
-@item ?
-@kindex ? (Summary)
+@item ?
+@kindex ? (Summary)
 @findex gnus-summary-describe-briefly
 Give a very brief description of the most important summary keystrokes
 (@code{gnus-summary-describe-briefly}). 
-@item C-c C-i
-@kindex C-c C-i (Summary)
+@item i
+@kindex i (Summary)
 @findex gnus-info-find-node
 Go to the Gnus info node (@code{gnus-info-find-node}).
 @end table
@@ -2778,6 +4084,7 @@ the look, or anything else you feel like.  I don't care.
 
 @node The Article Buffer
 @chapter The Article Buffer
+@cindex article buffer
 
 The articles are displayed in the article buffer, of which there is only
 one.  All the summary buffer share the same article buffer.
@@ -2792,56 +4099,58 @@ one.  All the summary buffer share the same article buffer.
 
 @node Hiding Headers
 @section Hiding Headers
+@cindex hiding headers
+@cindex deleting headers
 
 The top section of each article is the @dfn{header}.  (The rest is the
 @dfn{body}, but you may have guessed that already.) 
 
 @vindex gnus-show-all-headers
-There is a lot of information in the header - the name of the person who
-wrote the article, the date and the subject of the article.  That might
-be very useful, buf there's also lots of information most people do not
-want to see - what systems the article has passed through before
+There is a lot of useful information in the header: the name of the
+person who wrote the article, the date and the subject of the article.
+That 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 message id, the references, etc. ad nauseum - 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 t.
+@code{gnus-show-all-headers} to @code{t}.
 
 Gnus provides you with two variables for sifting header lines:
 
 @table @code
 @item gnus-visible-headers
 @vindex gnus-visible-headers
-If this variable is non-nil, it should be a regular expression that says
-what header lines you wish to keep in the article buffer.  All header
-lines that does not match this variable will be hidden.
+If this variable is non-@code{nil}, it should be a regular expression
+that says what header lines you wish to keep in the article buffer.  All
+header lines that does not match this variable will be hidden.
 
 For instance, if you only want to see the name of the person who wrote
 the article and the subject, you'd say:
 
-@example
+@lisp
 (setq gnus-visible-headers "^From:\\|^Subject:")
-@end example
+@end lisp
 
 @item gnus-ignored-headers
 @vindex gnus-ignored-headers
 This variable is the reverse of @code{gnus-visible-headers}.  If this
-variable is set (and @code{gnus-visible-headers} is nil), it should be a
-regular expression that matches all lines that you want to hide.  All
-lines that does not match this variable will remain visible.
+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 does not match this variable will remain visible.
 
 For instance, if you just want to get rid of the references line and the
 xref line, you might say:
 
-@example
-(setq gnus-ignored-headers "^References:\\^Xref:")
-@end example
+@lisp
+(setq gnus-ignored-headers "^References:\\|^Xref:")
+@end lisp
 
-Note that if @code{gnus-visible-headers} is non-nil, this variable will
-have no effect.
+Note that if @code{gnus-visible-headers} is non-@code{nil}, this
+variable will have no effect.
 @end table
 
 @vindex gnus-sorted-header-list
-Gnus can also sort the headers for you.  (It does this by default.) You
+Gnus can also sort the headers for you.  (It does this by default.)  You
 can control the sorting by setting the @code{gnus-sorted-header-list}
 variable.  It is a list of regular expressions that says in what order
 the header lines are to be displayed.
@@ -2849,16 +4158,17 @@ the header lines are to be displayed.
 For instance, if you want the name of the author of the article first,
 and then the subject, you might say something like:
 
-@example
+@lisp
 (setq gnus-sorted-header-list '("^From:" "^Subject:"))
-@end example
+@end lisp
 
 Any headers that are to remain visible, but are not listed in this
-variable, will be displayed after all the headers that are listed in
-this variable.
+variable, will be displayed in random order after all the headers that
+are listed in this variable.
 
 @node Using Mime
 @section Using Mime
+@cindex MIME
 
 Mime is a standard for waving your hands through the air, aimlessly,
 while people stand around yawning.
@@ -2874,22 +4184,22 @@ other naughty stuff in innocent-looking articles.
 @vindex gnus-show-mime-method
 Gnus handles MIME by shoving the articles through
 @code{gnus-show-mime-method}, which is @code{metamail-buffer} by
-default.  Set @code{gnus-show-mime} to t if you want to use MIME all the
+default.  Set @code{gnus-show-mime} to @code{t} if you want to use MIME all the
 time; it might be best 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, MIME has
-decoded the sounds file in the article and some horrible sing-a-long
-song comes streaming out 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.
+group @samp{alt.sing-a-long} and, before you know it, MIME has decoded
+the sounds file in the article and some horrible sing-a-long song comes
+streaming out 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.
 
 @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
@@ -2909,18 +4219,18 @@ makes in The Hands Of The Mad; @code{gnus-article-treat-overstrike}
 @code{gnus-article-remove-cr} (which removes trailing carriage returns).
 
 You can, of course, write your own functions.  The functions are called
-in 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.
+in 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.
 
 @node Article Keymap
 @section Article Keymap
 
 Most of the keystrokes in the summary buffer can also be used in the
-article buffer. They should behave as if you typed them in the summary
+article buffer.  They should behave as if you typed them in the summary
 buffer, which means that you don't actually have to have a summary
-buffer displayed when you're reading. You can do it all from the article
-buffer.
+buffer displayed when you're reading.  You can do it all from the
+article buffer.
 
 A few additional keystrokes are available:
 
@@ -2933,18 +4243,18 @@ Scroll forwards one page (@code{gnus-article-next-page}).
 @kindex DEL (Article)
 @findex gnus-article-prev-page
 Scroll backwards one page (@code{gnus-article-prev-page}).
-@item C-x r
-@kindex C-x r (Article)
+@item C-c ^
+@kindex C-c ^ (Article)
 @findex gnus-article-refer-article
 If point is in the neighborhood of a message-id and you press @kbd{r},
 Gnus will try to get that article from the server.  (Only available with
 nntp).  (@code{gnus-article-refer-article}).
-@item C-m
-@kindex C-m (Article)
+@item C-c C-m
+@kindex C-c C-m (Article)
 @findex gnus-article-mail
 Send a reply to the address near point (@code{gnus-article-mail}). 
-@item C-M
-@kindex C-M (Article)
+@item C-c C-M
+@kindex C-c C-M (Article)
 @findex gnus-article-mail-with-original
 Send a reply to the address near point and include the original article
 (@code{gnus-article-mail-with-original}). 
@@ -2963,28 +4273,34 @@ Give a very brief description of the available keystrokes
 @node Misc Article
 @section Misc Article
 
-@vindex gnus-article-display-hook
+@table @code
 @vindex gnus-article-prepare-hook
-The @code{gnus-article-prepare-hook} is called right after the article
-has been inserted into the 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.  Use the @code{gnus-article-display-hook} for that, which is
-called after this hook is called.
-
+@item gnus-article-prepare-hook
+This hook is called right after the article has been inserted into the
+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, highlight, hiding
+headers, and the like.
 @vindex gnus-article-mode-line-format
-@code{gnus-article-mode-line-format} is a format string along the same
-lines as @code{gnus-summary-mode-line-format}.  It accepts exactly the
-same format specifications as that variable.
-
+@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 exactly the same
+format specifications as that variable.
 @vindex gnus-break-pages
-The @code{gnus-break-pages} variable controls whether @dfn{page
-breaking} is to take place.  If this variable is non-nil, the articles
-will be divided into pages whenever a @code{gnus-page-delimiter} appears
-in the article.  If this variable is nil, paging will not be done.
-
+@item gnus-break-pages
+Controls whether @dfn{page breaking} is to take place.  If this variable
+is non-@code{nil}, the articles will be divided into pages whenever a
+page delimeter appears in the article.  If this variable is @code{nil},
+paging will not be done.
+@item gnus-page-delimeter
 @vindex gnus-page-delimiter
-@code{gnus-page-delimiter} is @samp{^L} (form linefeed) by default.
+This is the delimeter mentioned above.  By default, it is @samp{^L}
+(form linefeed).
+@end table
 
 @node Various
 @chapter Various
@@ -2997,26 +4313,27 @@ in the article.  If this variable is nil, paging will not be done.
 
 @node Interactive
 @section Interactive
+@cindex interaction
 
 @table @code
 @item gnus-novice-user
 @vindex gnus-novice-user
-If this variable is non-nil, you are either a newcomer to the usenet
-world, or you are very cautious, which is a nice thing to be,
+If this variable is non-@code{nil}, you are either a newcomer to the
+usenet world, 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.
 @item gnus-expert-user
 @vindex gnus-expert-user
-If this variable is non-nil, you will never ever be asked any questions
-by Gnus.  It will simply assume you know what your are doing, no matter
-how strange.
+If this variable is non-@code{nil}, you will never ever be asked any
+questions by Gnus.  It will simply assume you know what your are doing,
+no matter how strange.
 @item gnus-interactive-catchup
 @vindex gnus-interactive-catchup
-Require confirmation before catching up a group if non-nil.
+Require confirmation before catching up a group if non-@code{nil}.
 @item gnus-interactive-post
 @vindex gnus-interactive-post
-If non-nil, the user will be prompted for a group name when posting
-an article.
+If non-@code{nil}, the user will be prompted for a group name when
+posting an article.
 @item gnus-interactive-exit
 @vindex gnus-interactive-exit
 Require confirmation before exiting Gnus.
@@ -3024,25 +4341,26 @@ Require confirmation before exiting Gnus.
 
 @node Windows Configuration
 @section Windows Configuration
+@cindex windows configuration
 
 No, there's nothing here about X, so be quiet.
 
 @table @code
 @item gnus-use-full-window
 @vindex gnus-use-full-window
-If non-nil, Gnus will delete all other windows and occupy the entire
-Emacs screen by itself.  It is t by default.
+If 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-window-configuration
 @vindex gnus-window-configuration
 This variable describes how much space each Gnus buffer should be given,
 compared to the other Gnus buffers.  Here's an example:
 
-@example
+@lisp
 (setq gnus-window-configuration
   '((summary (0 1 0))
     (groups (1 0 0))
     (article (0 3 10))))
-@end example
+@end lisp
 
 This variable is a list of lists, where each of these small lists is on
 the form @var{(action (g s a))}.  As you can see, there are three
@@ -3061,44 +4379,55 @@ This variable can also have a function as its value.  In that case,
 whenever Gnus tries to configure the Gnus buffers, that function will be
 called with the @var{action} as its parameter.  There is one pre-made
 function supplied, @code{gnus-window-configuration-split}, which may be
-suitable if you have a very wide Emacs window, and wants to have the
-summary buffer and the article buffer side by side.  Here's the
-definition of this function, which you may use as a template for your
-own function(s):
-
-@example
-(defun gnus-window-configuration-split (action)
-  ;; The group buffer always exists, so it's nice to use 
-  ;; it as a starting point.
-  (switch-to-buffer gnus-group-buffer t)
-  (delete-other-windows)
-  (split-window-horizontally)
-  (cond ((or (eq action 'group) (eq action 'summary))
-        (if (and (get-buffer gnus-summary-buffer)
-                 (buffer-name gnus-summary-buffer))
-            (switch-to-buffer-other-window gnus-summary-buffer)))
-       ((eq action 'article)
-        (switch-to-buffer gnus-summary-buffer t)
-        (other-window 1)
-         ;; Create and initialize the article buffer if it doesn't
-         ;; exist.
-        (gnus-article-setup-buffer)
-        (switch-to-buffer gnus-article-buffer t))))
-@end example
+suitable if you have a very wide Emacs window, and want to have the
+summary buffer and the article buffer side by side.
 @end table
 
 @node Various Various
 @section Various Various
+@cindex mode lines
+@cindex highlights
 
+@table @code
+@item gnus-updated-mode-lines
 @vindex gnus-updated-mode-lines
-The @code{gnus-updated-mode-lines} variable is a list of buffers that
-should keep their mode lines updated.  The list may contain the symbols
-`group', `article' and `summary'.  If the corresponding symbol is
-present, Gnus will keep that mode line updated with information that may
-be pertinent.  If this variable is nil, screen refresh may be quicker.
+This is a list of buffers that should keep their mode lines updated.
+The list may contain the symbols `group', `article' and `summary'.  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 gnus-mode-non-string-length
+@vindex gnus-mode-non-string-length
+By default, Gnus displays information of article in the mode lines of
+the summary and article buffers.  The information Gnus wishes to display
+(eg. the subject of the article) is often longer than the mode lines,
+and therefore have to be cut off at some point.  This variable says how
+long the other info on the line is (ie. the non-info part).  If you put
+additional elements on the mode line (eg. a clock), you should modify
+this variable:
+@c Hook written by Keinonen Kari <kk85613@cs.tut.fi>.
+@lisp
+(add-hook 'display-time-hook
+         (lambda ()
+           (setq gnus-mode-non-string-length
+                 (+ 21 (length display-time-string)))))
+@end lisp
+
+@item gnus-visual
+@vindex gnus-visual
+If @code{nil}, Gnus won't attempt to create menus or use fancy colours
+or fonts.  This will also inhibit loading the @file{gnus-visual.el}
+file.
+@item gnus-mouse-face
+@vindex gnus-mouse-face
+This is the face (ie. font) used for mouse highlighting in Gnus.  No
+mouse highlights will be done if @code{gnus-visual} is @code{nil}.
+@end table
 
 @node Customization
 @chapter Customization
+@cindex general customization
 
 All variables are properly documented elsewhere in this manual.  This
 section is designed to give general pointers on how to customize Gnus
@@ -3120,16 +4449,16 @@ Gnus has to get from the NNTP server.
 
 @table @code
 @item gnus-read-active-file
-Set this to nil, which will inhibit Gnus from requesting the entire active
-file from the server.  This file is often v. large.  You also have to set
-@code{gnus-check-new-news} and @code{gnus-check-bogus-newsgroups} to nil
-to make sure that Gnus doesn't suddenly decide to fetch the active file
-anyway.  Note that this will make it difficult for you to get hold of new
-groups. 
-@item nntp-xover-is-evil
-This one has to be nil.  If not, grabbing article headers from the NNTP
-server will not be very fast.  Not all NNTP servers support XOVER; Gnus
-will detect this by itself.
+Set this to @code{nil}, which will inhibit Gnus from requesting the
+entire active file from the server.  This file is often v.  large.  You
+also have to set @code{gnus-check-new-news} and
+@code{gnus-check-bogus-newsgroups} to @code{nil} to make sure that Gnus
+doesn't suddenly decide to fetch the active file anyway.  Note that this
+will make it difficult for you to get hold of new groups.
+@item gnus-nov-is-evil
+This one has to be @code{nil}.  If not, grabbing article headers from
+the NNTP server will not be very fast.  Not all NNTP servers support
+XOVER; Gnus will detect this by itself.
 @end table
 
 @node Slow Terminal Connection
@@ -3141,31 +4470,31 @@ amount of data that is sent over the wires as much as possible.
 
 @table @code
 @item gnus-auto-center-summary
-Set this to nil to inhibit Gnus from recentering the summary buffer all
-the time.
+Set this to @code{nil} to inhibit Gnus from recentering the summary
+buffer all the time.
 @item gnus-visible-headers
 Cut down on the headers that are included in the articles to the
 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{""} or @samp{"^Date:"}, or whatever you feel you need.
+@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:
-@example
+@lisp
 (setq gnus-article-display-hook 
       '(gnus-article-hide-headers gnus-article-hide-signature
         gnus-article-hide-citation))
-@end example
+@end lisp
 @item gnus-use-full-window
-By setting this to nil, you can make all the windows smaller.  While this
-doesn't really cut down much generally, it means that you have to see
-smaller portions of articles before deciding that you didn't want to
-read them anyway.
+By setting this to @code{nil}, you can make all the windows smaller.
+While this doesn't really cut down much generally, it means that you
+have to see smaller portions of articles before deciding that you didn't
+want to read them anyway.
 @item gnus-thread-hide-subtree
-If this is non-nil, all threads in the summary buffer will be hidden
-initially. 
+If this is non-@code{nil}, all threads in the summary buffer will be
+hidden initially.
 @item gnus-updated-mode-lines
-If this is nil, Gnus will not put information in the buffer mode lines,
-which might save some time.
+If this is @code{nil}, Gnus will not put information in the buffer mode
+lines, which might save some time.
 @end table
 
 @node Little Disk Space
@@ -3176,16 +4505,15 @@ sizes down a bit if you are running out of space.
 
 @table @code
 @item gnus-save-newsrc-file
-If this is 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. 
+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.
 @item gnus-save-killed-list
-If this is nil, Gnus will not save the list of dead groups.  That
-means that Gnus will not know whether groups are new or old, which
-makes automatic handling of new groups impossible.  You should also
-set @code{gnus-check-new-newsgroups} and
-@code{gnus-check-bogus-newsgroups} to nil if you set this variable to
-nil. 
+If this is @code{nil}, Gnus will not save the list of dead groups.  That
+means that Gnus will not know whether groups are new or old, which makes
+automatic handling of new groups impossible.  You should also set
+@code{gnus-check-new-newsgroups} and @code{gnus-check-bogus-newsgroups}
+to @code{nil} if you set this variable to @code{nil}.
 @end table
 
 @node Slow Machine
@@ -3195,28 +4523,50 @@ If you have a slow machine, or are just really impatient, there are a
 few things you can do to make Gnus run faster.
 
 Set @code{gnus-read-active-file}, @code{gnus-check-new-newsgroups},
-@code{gnus-check-bogus-newsgroups} to nil to make startup faster. 
+@code{gnus-check-bogus-newsgroups} to @code{nil} to make startup faster.
 
 Set @code{gnus-show-threads}, @code{gnus-use-cross-reference} and
-@code{nntp-xover-is-evil} to nil to make entering and exiting the
+@code{nntp-xover-is-evil} to @code{nil} to make entering and exiting the
 summary buffer faster.
 
-Set @code{gnus-article-display-hook} to nil to make article processing a
-bit faster.
+Set @code{gnus-article-display-hook} to @code{nil} to make article
+processing a bit faster.
 
 @node Troubleshooting
 @chapter Troubleshooting
+@cindex troubleshooting
+
+(ding) Gnus work so well straight out of the box, so I can't imagine any
+problems, really.  
+
+Ahem.
+
+Make sure your computer is switched on.
+
+Make sure that you really load the current Gnus version.  If you have
+been running @sc{GNUS}, you need to exit Emacs and start it up again before
+Gnus will work.
+
+Read the help group (@kbd{M h} in the group buffer) for a FAQ and a
+how-to. 
+
+If all else fails, report the problem as a bug (@pxref{Reporting
+Bugs}). 
 
 @node Reporting Bugs
 @chapter Reporting Bugs
+@cindex bugs
+@cindex reporting bugs
 
+@kindex M-x gnus-bug
+@findex gnus-bug
 If you find a bug in (ding) Gnus, you can report it with the @kbd{M-x
-gnus-bug} command. @code{(setq debug-on-error t)}, and send me the
-backtrace. I will fix bugs, but I can only fix them if you send me a
+gnus-bug} command.  @code{(setq debug-on-error t)}, 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.
 
 If you just need help, you are better off asking on
-@samp{gnu.emacs.gnus}. 
+@samp{gnu.emacs.gnus}.
 
 @node Index
 @chapter Index