*** empty log message ***
authorLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 4 Mar 1997 06:32:55 +0000 (06:32 +0000)
committerLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 4 Mar 1997 06:32:55 +0000 (06:32 +0000)
22 files changed:
lisp/ChangeLog
lisp/doc.txt
lisp/gnus-cache.el
lisp/gnus-cus.el
lisp/gnus-mh.el
lisp/gnus-msg.el
lisp/gnus-score.el
lisp/gnus-topic.el
lisp/gnus-uu.el
lisp/gnus-vis.el
lisp/gnus-xmas.el
lisp/gnus.el
lisp/nndoc.el
lisp/nnfolder.el
lisp/nnheader.el
lisp/nnkiboze.el
lisp/nnmail.el
lisp/nnml.el
lisp/nntp.el
texi/ChangeLog
texi/Makefile
texi/gnus.texi

index 5d806d5..14c9b14 100644 (file)
@@ -1,5 +1,164 @@
-Sun Dec 10 10:38:47 1995  Lars Magne Ingebrigtsen  <larsi@narfi.ifi.uio.no>
+Thu Dec 14 10:48:51 1995  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
 
+       * gnus.el (gnus-summary-toggle-header): Don't do that hook dance.
+
+Thu Dec 14 10:02:08 1995  Lars Magne Ingebrigtsen  <larsi@narfi.ifi.uio.no>
+
+       * gnus-xmas.el (gnus-xmas-read-event-char): New function.
+
+       * gnus.el (gnus-summary-last-subject): New function.
+       (gnus-summary-next-article): Understand all key events.
+       (gnus-summary-walk-group-buffer): New function.
+       (gnus-read-event-char): New function.
+
+Wed Dec 13 16:06:29 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus-msg.el (gnus-new-mail, gnus-mail-reply): Didn't insert
+       Gcc. 
+
+       * gnus-score.el (gnus-score-load-file): Allow `adapt-file' atom. 
+       (gnus-score-adaptive): Use it.
+
+       * gnus.el (gnus-group-visible-select-group): New command and
+       keystroke. 
+       (gnus-read-save-file-name): Extend the syntax of
+       `gnus-split-methods'.
+       (gnus-article-archive-name): New function.
+       (gnus-split-methods): New default; use function above.
+       (gnus-summary-update-secondary-mark): Update highlighting after
+       setting secondary marks.
+
+       * nnfolder.el (nnfolder-request-group): Don't load all nnfolder
+       groups on startup.
+
+Tue Dec 12 19:48:55 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-group-insert-group-line): Number of marked (etc)
+       didn't work.
+
+Tue Dec 12 19:37:05 1995  Timo Metzemakers  <metzemakers@labri.u-bordeaux.fr>
+
+       * gnus.el (gnus-summary-reselect-current-group): Really reselect
+       the group. 
+
+Tue Dec 12 10:38:05 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * nnmail.el (nnmail-days-to-time): Would result in short expiry
+       times in groups with veeery long expiry times.
+
+       * gnus-vis.el (gnus-summary-highlight-line): Bind `number'.
+
+       * gnus-score.el (gnus-score-find-bnews): Protect agains bogus
+       score file names.
+
+       * gnus.el (gnus-activate-all-groups): New command and keystroke.
+
+       * gnus-vis.el (gnus-article-prev-button): New command and keystroke.
+
+       * gnus-cache.el (gnus-cache-generate-nov-databases): New command. 
+
+       * gnus-score.el (gnus-score-load-file): Accept
+       `thread-mark-and-expunge' atom.
+
+       * gnus.el (gnus-newsgroup-saved): New variable.
+       (gnus-summary-set-saved-mark): New function.
+       (gnus-kill-summary-on-exit): New variable.
+       (gnus-dead-summary-mode): New minor mode.
+       (gnus-deaden-summary, gnus-summary-wake-up-the-dead): New
+       functions. 
+       (gnus-summary-catchup-and-goto-next-group): Respect
+       `gnus-auto-select-next', etc. 
+       (gnus-article-hide-headers): New implementation.
+       (gnus-article-header-rank): New function.
+       (gnus-article-header-less): Ditto.
+       (gnus-visible-headers, gnus-ignored-headers): Can now be lists of
+       regexps. 
+       (gnus-thread-expunge-below): New variable.
+       (gnus-expunge-thread): New variable.
+
+       * gnus-mh.el (gnus-summary-save-in-folder): There is no
+       `mh-search-path'. 
+
+Mon Dec 11 07:21:25 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el (gnus-article-sort-functions): New variable.
+       (gnus-article-sort-by-number, gnus-article-sort-by-author,
+       gnus-article-sort-by-subject, gnus-article-sort-by-date, 
+       (gnus-article-sort-by-score): New functions.
+       (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-summary-sort-by-number,
+       gnus-summary-sort-by-author, gnus-summary-sort-by-subject,
+       gnus-summary-sort-by-date, gnus-summary-sort-by-score,
+       gnus-summary-sort):  New implementations.
+       (gnus-summary-mode-line-format): Doc fix.
+       (gnus-insert-pseudo-articles): New variable.
+       (gnus-activate-level): New variable.
+       (gnus-get-unread-articles): Use it.
+
+       * nnkiboze.el (nnkiboze-request-delete-group): New function.
+
+       * gnus.el (gnus-subscribe-killed): New function.
+       (gnus-group-kill-group): Make mass group slaughter faster.
+       (gnus-group-kill-level): New command and keystroke.
+
+       * gnus-cache.el (gnus-cache-generate-active): Messed up the active
+       file. 
+
+       * gnus.el (gnus-summary-update-secondary-mark): New function.
+       (gnus-cached-mark): New variable.
+       (gnus-gmt-to-local): Removed function.
+       (gnus-narrow-to-page): New implementation.
+
+       * gnus-cache.el (gnus-cache-enter-article): New command and
+       keystroke. 
+       (gnus-cache-remove-article): Ditto.
+       (gnus-passive-cache): New variable.
+       (gnus-cached-article-p): New function.
+
+       * gnus.el (gnus-summary-mode-line-format,
+       gnus-article-mode-line-format, gnus-group-mode-line-format):
+       Include the buffer name in all mode lines.
+
+       * gnus-topic.el (gnus-topic-yank-group, gnus-topic-kill-group):
+       Allow kill/yank inside and in between topics.
+
+       * gnus.el (gnus-request-type): Wouldn't work.
+
+Sun Dec 10 13:16:49 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus-topic.el (gnus-topic-insert-topic-line): Remove old text
+       properties before setting new.
+
+       * nnml.el: Understand jka-compr.
+       (nnml-generate-nov-databases): Would make empty group disappear. 
+
+       * nnheader.el (nnheader-numerical-short-files): New variable.
+       (nnheader-numerical-full-files): Ditto.
+
+       * gnus-msg.el (gnus-summary-resend-message): Rename old Resent-*
+       headers. 
+
+       * gnus-cache.el (gnus-cache-retrieve-headers): Allow fetching of
+       old headers. 
+
+       * nnmail.el (nnmail-get-spool-files): Don't ditch procmail
+       symlinks. 
+
+       * gnus-msg.el (gnus-inews-insert-signature): Don't insert
+       signature if mail-signature.
+
+       * gnus.el (gnus-group-make-help-group): Find gnus-tut in the etc
+       directory. 
+
+Sun Dec 10 12:29:54 1995  Lars Magne Ingebrigtsen  <larsi@narfi.ifi.uio.no>
+
+       * gnus.el (gnus-article-date-ut): Bugged out on pseudos.
+
+Sun Dec 10 10:38:47 1995  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: 0.21 is released.
+       
        * gnus.el (gnus-backlog-shutdown): New function.
        (gnus-backlog-buffer): Would return a list the first time called. 
 
index e69de29..90e6eca 100644 (file)
@@ -0,0 +1,374 @@
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: This is a test version of this group
+Message-ID: <lars-doc0@eyesore.no>
+
+This group will look something like this, but the stuff in here is of
+little worth right now. 
+
+For real documentation, you'll have to read the source code. Or you
+can read the info file, which is pretty comprehensive, if somewhat out
+of date.
+
+Gnus is currently in beta.
+
+When you happen upon a bug, please drop me a note.
+
+
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: So you want to use the new Gnus
+Message-ID: <lars-doc1@eyesore.no>
+
+Actually, since you are reading this, chances are you are already
+using the new Gnus. Congratulations.
+
+This entire newsgroup you are reading is, in fact, no real newsgroup
+at all, in the traditional sense. It is an example of one of the
+"foreign" select methods that Gnus may use.
+
+The text you are now reading is stored in the "etc" directory with the
+rest of the Emacs sources. You are using the "nndir" backend for
+accessing it. Scary, isn't it?
+
+This isn't the real documentation. `M-x info', `m gnus <RET>' to read
+that. This "newsgroup" is intended as a kinder, gentler way of getting
+people started.
+
+Gnus is a rewrite of GNUS 4.1, written by Masanobu Umeda. The rewrite
+was done by moi, yours truly, your humble servant, Lars Magne
+Ingebrigtsen. If you have a WWW browser, you can investigate to your
+heart's delight at "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
+Subject: Starting up
+Message-ID: <lars-doc2@eyesore.no>
+
+If you are having problems with Gnus not finding your server, you have
+to set `gnus-select-method'. A "method" is a way of specifying *how*
+the news is to be found, and from *where*.
+
+Say you want to read news from you local, friendly nntp server
+"news.my.local.server". 
+
+(setq gnus-select-method '(nntp "news.my.local.server"))
+
+Quite easy, huh?
+
+From the news spool:
+
+(setq gnus-select-method '(nnspool ""))
+
+From your mh-e spool:
+
+(setq gnus-select-method '(nnmh ""))
+
+There's a whole bunch of other methods for reading mail and news, see
+the "Foreign groups" article for that.
+
+
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: Where are all the groups, then?
+Message-ID: <lars-doc3@eyesore.no>
+
+If this is the first time you have used a newsreader, you won't have a
+.newsrc file. This means that Gnus will think that all the newsgroups
+on the server are "new", and kill them all.
+
+If you have a .newsrc file, the new groups will be processed with the
+function in the `gnus-subscribe-newsgroup-method' variable, which is
+`gnus-subscribe-zombies' by default.
+
+This means that all the groups have been made into "zombies" - not
+quite dead, but not exactly alive, either.
+
+Jump back to the *Group* buffer, and type `C-c C-z' to list all the
+zombie groups. Look though the list, and subscribe to the groups you
+want to read by pressing `u' on the one you think look interesting. 
+
+If all the groups have been killed, type `C-c C-k' to list all the
+killed groups. Subscribe to them the same way.
+
+When you are satisfied, press `M-z' to kill all the zombie groups. 
+
+Now you should have a nice list of all groups you are interested in.
+
+(If you later want to subscribe to more groups, press `C-c C-k' to
+list all the kill groups, and repeat. You can also type `U' and be
+prompted for groups to subscribe to.)
+
+
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: I want to read my mail!
+Message-ID: <lars-doc4@eyesore.no>
+
+Yes, Virginia, you can read mail with Gnus.
+
+First you have to decide which mail backend you want to use. You have
+nnml, which is a one-file-one-mail backend, which is quite nice, but
+apt to make your systems administrator go crazy and come after you
+with a shotgun.
+
+nnmbox uses a Unix mail box to store mail. Nice, but slow.
+
+nnmh uses mh-e folders, which is also a one-file-one-mail thingie, but
+slower than nnml. (It doesn't support NOV files.)
+
+So if you want to go with nnmbox, you can simply say:
+
+(setq gnus-secondary-select-methods '((nnmbox "")))
+
+(The same for the other methods, kind of.)
+
+You should also set `nnmail-split-methods' to something sensible: 
+
+(setq nnmail-split-methods 
+      '(("mail.junk" "From:.*Lars")
+       ("mail.misc "")))
+
+This will put all mail from me in you junk mail group, and the rest in
+"mail.misc". 
+
+These groups will be subscribe the same way as the normal groups, so
+you will probably find them among the zombie groups after you set
+these variables and re-start Gnus.
+
+
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: Foreign newsgroups
+Message-ID: <lars-doc5@eyesore.no>
+
+These are groups that do not come from `gnus-select-method'. 
+
+Say you want to read "alt.furniture.couches" from "news.funet.fi". You
+can then either type `B news.funet.fi <RET>' to browse that server and
+subscribe to that group, or you can type 
+`M-a alt.furniture.couches<RET>nntp<RET>news.funet.fi<RET>', if you
+like to type a lot.
+
+If you want to read a directory as a newsgroup, you can create an
+nndir group, much the same way. There's a shorthand for that,
+though. If, for instance, you want to read the (ding) list archives,
+you could type `D /ftp <RET>'.
+
+There's lots more to know about foreign groups, but you have to read
+the info pages to find out more.
+
+
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: Low level changes in GNUS, or, Wrong type argument: stringp, nil
+Message-ID: <lars-doc6@eyesore.no>
+
+Gnus really isn't GNUS, even though it looks like it. If you scrape
+the surface, you'll find that most things have changed.
+
+This means that old code that relies on GNUS internals will fail. 
+
+In particular, `gnus-newsrc-hashtb', `gnus-newsrc-assoc',
+`gnus-killed-list', the `nntp-header-' macros and the display formats
+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.
+
+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.
+
+       
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: Bugs & stuff
+Message-ID: <lars-doc7@eyesore.no>
+
+If you want to report a bug, please type `M-x gnus-bug'. This will
+give me a precice overview of your Gnus and Emacs version numbers,
+along with a look at all Gnus variables you have changed.
+
+Du not expect a reply back, but your bug should be fixed in the next
+version. If the bug persists, please re-submit your bug report.
+
+When a bug occurs, I need a recipe for how to trigger the bug. You
+have to tell me exactly what you do to uncover the bug, and you should
+(setq debug-on-error t) and send me the backtrace along with the bug
+report. 
+
+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 "ding@ifi.uio.no" mailing list
+is where to post the questions.
+
+
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: How do I re-scan my mail groups?
+Message-ID: <lars-doc8@eyesore.no>
+
+Reading the active file from the nntp server is a drag.
+
+Just press `M-g' on the mail groups, and they will be re-scanned.
+
+You can also re-scan all the mail groups by putting them on level 1
+(`1 S'), and saying `1 g' to re-scan all level 1 groups.
+
+
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: How do I set up virtual newsgroups?
+Message-ID: <lars-doc9@eyesore.no>
+
+Virtual newsgroups are collections of other newsgroups. Why people
+want this is beyond me, but here goes:
+
+Create the group by saying
+
+`M-a my.virtual.newsgroup<RET>nnvirtual<RET>^rec\.aquaria\.*<RET>'
+
+This will create the group "nnvirtual:my.virtual.newsgroup", which
+will collect all articles from all the groups in the "rec.aquaria"
+hierarchy. 
+
+If you want to edit the regular expression, just type `M-e' on the
+group line.
+
+Note that all the groups that are part of the virtual group have to be
+alive. This means that the cannot, absolutely not, be zombie or
+killed. They can be unsubscribed; that's no problem.
+
+You can combine groups from different servers in the same virtual
+newsgroup, something that may actually be useful. Say you have the
+group "comp.headers" on the server "news.server.no" and the same group
+on "news.server.edu". If people have posted articles with Distribution
+headers that stop propagation of their articles, combining these two
+newsgroups into one virtual newsgroup should give you a better view of
+what's going on.
+
+One caveat, though: The virtual group article numbers from the first
+source group (group A) will always be lower than the article numbers
+from the second (group B). This means that Gnus will believe that
+articles from group A are older than articles from group B. Threading
+will lessen these problems, but it might be a good idea to sort the
+threads over the date of the articles to get a correct feel for the
+flow of the groups:
+
+(setq gnus-thread-sort-functions '(gnus-thread-sort-by-date))
+
+If you only want this in virtual groups, you could say something along
+the lines of:
+
+(setq gnus-select-group-hook
+      (lambda ()
+       (if (eq 'nnvirtual (car (gnus-find-method-for-group 
+                                 gnus-newsgroup-name)))
+           (progn
+             (make-local-variable 'gnus-thread-sort-functions)
+             (setq gnus-thread-sort-functions '(gnus-thread-sort-by-date))))))
+
+
+From lars Thu Feb 23 23:20:38 1995
+From: larsi@ifi.uio.no (ding)
+Date: Fri Feb 24 13:40:45 1995
+Subject: I want to kiboze everything in sight!
+Message-ID: <lars-doc10@eyesore.no>
+
+The nnkiboze backend collects articles that you are interested in from
+groups you are interested in. Below is a description for how you can
+gather all posts from me, and all posts about Gnus in the gnu.emacs
+hierarchy in one handy, easy to read group.
+
+Gnus will let you eat up all available machine resources, grinding
+everything to a halt. Including your nntp server. Who says Gnus isn't
+friendly? 
+
+You want to do this, of course.
+
+Create an nnkiboze group the normal way:
+
+`M-a my.group<RET>nnkiboze<RET>^gnu.emacs.*<RET>'
+
+You now have a shiny new group that you can't enter.  How...
+practical.
+
+But just wait, it gets worse.
+
+You now have to create a score file. 
+
+`C-x C-f ~/News/nnkiboze:my.group.SCORE<RET>'
+
+Put something like the following in this file:
+
+(setq gnus-score-alist
+      '(("from"
+        ("Ingebrigtsen" nil 1000)
+        ("lmi" nil 5000))
+       ("subject"
+        ("Gnus" nil 10000))
+       (touched)))
+
+Save the file, and go to a shell window.
+
+Type:
+
+$ emacs -batch -l ~/.emacs -l nnkiboze -f nnkiboze-generate-groups
+
+Wait a few hours, and all articles from me, or articles about Gnus,
+will appear, as if by magic, in the nnkiboze group. You really want
+that, of course.
+
+Gnus actually grabs the headers of all the groups that supply the
+nnkiboze group with articles, so this isn't very kind. Pleasy only do
+it at night (`at' is a fine command), and please, *please*, limit the
+number of groups that supply articles to the group. If you specify ""
+as the address of this group, nnkiboze will ask for headers from *all*
+groups, and this is megs and megs and megs of data. 
+
+Use it, don't abuse it. Be nice.
+
+
+
+
index c8bab9d..91f1f8d 100644 (file)
@@ -52,7 +52,6 @@ variable to \"^nnml\".")
 ;;; Internal variables.
 
 (defvar gnus-cache-buffer nil)
-(defvar gnus-group-alist nil)
 (defvar gnus-cache-active-hashtb nil)
 (defvar gnus-cache-active-altered nil)
 
@@ -67,6 +66,7 @@ variable to \"^nnml\".")
 (defun gnus-cache-close ()
   "Shut down the cache."
   (gnus-cache-write-active)
+  (gnus-cache-save-buffers)
   (setq gnus-cache-active-hashtb nil))
 
 (defun gnus-cache-save-buffers ()
@@ -102,65 +102,68 @@ variable to \"^nnml\".")
       (setq gnus-cache-buffer nil))))
 
 (defun gnus-cache-possibly-enter-article 
-  (group article headers ticked dormant unread)
-  (let ((number (mail-header-number headers))
-       file dir)
-    (if (or (not (vectorp headers))    ; This might be a dummy article.
-           (< number 0)                ; Reffed article.
-           (and gnus-uncacheable-groups
-                (string-match gnus-uncacheable-groups group))
-           (not (gnus-cache-member-of-class
-                 gnus-cache-enter-articles ticked dormant unread))
-           (file-exists-p (setq file (gnus-cache-file-name group article))))
-       ()                              ; Do nothing.
-      ;; Possibly create the cache directory.
-      (or (file-exists-p (setq dir (file-name-directory file)))
-         (gnus-make-directory dir))
-      ;; Save the article in the cache.
-      (if (file-exists-p file)
-         t                             ; The article already is saved.
-       (let ((gnus-use-cache nil))
-         (gnus-summary-select-article))
-       (save-excursion
-         (set-buffer gnus-original-article-buffer)
-         (save-restriction
-           (widen)
-           (write-region (point-min) (point-max) file nil 'quiet))
-         (gnus-cache-change-buffer group)
-         (set-buffer (cdr gnus-cache-buffer))
-         (goto-char (point-max))
-         (forward-line -1)
-         (while (condition-case ()
-                    (and (not (bobp))
-                         (> (read (current-buffer)) number))
-                  (error
-                   ;; The line was malformed, so we just remove it!!
-                   (gnus-delete-line)
-                   t))
-           (forward-line -1))
-         (if (bobp) 
-             (if (not (eobp))
-                 (progn
-                   (beginning-of-line)
-                   (if (< (read (current-buffer)) number)
-                       (forward-line 1)))
-               (beginning-of-line))
-           (forward-line 1))
-         (beginning-of-line)
-         ;; [number subject from date id references chars lines xref]
-         (insert (format "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n"
-                         (mail-header-number headers)
-                         (mail-header-subject headers)
-                         (mail-header-from headers)
-                         (mail-header-date headers)
-                         (mail-header-id headers)
-                         (or (mail-header-references headers) "")
-                         (or (mail-header-chars headers) "")
-                         (or (mail-header-lines headers) "")
-                         (or (mail-header-xref headers) ""))))
-       ;; Update the active info.
-       (gnus-cache-update-active group number)
-       t))))
+  (group article headers ticked dormant unread &optional force)
+  (when (or force (not (eq gnus-use-cache 'passive)))
+    (let ((number (mail-header-number headers))
+         file dir)
+      (when (and (vectorp headers)     ; This might be a dummy article.
+                (> number 0)           ; Reffed article.
+                (or (not gnus-uncacheable-groups)
+                    (not (string-match gnus-uncacheable-groups group)))
+                (or force
+                    (gnus-cache-member-of-class
+                     gnus-cache-enter-articles ticked dormant unread))
+                (not (file-exists-p (setq file (gnus-cache-file-name
+                                                group article)))))
+       ;; Possibly create the cache directory.
+       (or (file-exists-p (setq dir (file-name-directory file)))
+           (gnus-make-directory dir))
+       ;; Save the article in the cache.
+       (if (file-exists-p file)
+           t                           ; The article already is saved.
+         (let ((gnus-use-cache nil))
+           (gnus-summary-select-article))
+         (save-excursion
+           (set-buffer gnus-original-article-buffer)
+           (save-restriction
+             (widen)
+             (write-region (point-min) (point-max) file nil 'quiet))
+           (gnus-cache-change-buffer group)
+           (set-buffer (cdr gnus-cache-buffer))
+           (goto-char (point-max))
+           (forward-line -1)
+           (while (condition-case ()
+                      (and (not (bobp))
+                           (> (read (current-buffer)) number))
+                    (error
+                     ;; The line was malformed, so we just remove it!!
+                     (gnus-delete-line)
+                     t))
+             (forward-line -1))
+           (if (bobp) 
+               (if (not (eobp))
+                   (progn
+                     (beginning-of-line)
+                     (if (< (read (current-buffer)) number)
+                         (forward-line 1)))
+                 (beginning-of-line))
+             (forward-line 1))
+           (beginning-of-line)
+           ;; [number subject from date id references chars lines xref]
+           (insert (format "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n"
+                           (mail-header-number headers)
+                           (mail-header-subject headers)
+                           (mail-header-from headers)
+                           (mail-header-date headers)
+                           (mail-header-id headers)
+                           (or (mail-header-references headers) "")
+                           (or (mail-header-chars headers) "")
+                           (or (mail-header-lines headers) "")
+                           (or (mail-header-xref headers) ""))))
+         ;; Update the active info.
+         (gnus-cache-update-active group number)
+         (push number gnus-newsgroup-cached)
+         t)))))
 
 (defun gnus-cache-enter-remove-article (article)
   "Mark ARTICLE for later possible removal."
@@ -169,22 +172,23 @@ variable to \"^nnml\".")
 
 (defun gnus-cache-possibly-remove-articles ()
   "Possibly remove some of the removable articles."
-  (let ((articles gnus-cache-removeable-articles)
-       (cache-articles (gnus-cache-articles-in-group gnus-newsgroup-name))
-       article)
-    (gnus-cache-change-buffer gnus-newsgroup-name)
-    (while articles
-      (if (memq (setq article (pop articles)) cache-articles)
-         ;; The article was in the cache, so we see whether we are
-         ;; supposed to remove it from the cache.
-         (gnus-cache-possibly-remove-article
-          article (memq article gnus-newsgroup-marked)
-          (memq article gnus-newsgroup-dormant)
-          (or (memq article gnus-newsgroup-unreads)
-              (memq article gnus-newsgroup-unselected))))))
-  ;; The overview file might have been modified, save it
-  ;; safe because we're only called at group exit anyway
-  (gnus-cache-save-buffers))
+  (unless (eq gnus-use-cache 'passive)
+    (let ((articles gnus-cache-removeable-articles)
+         (cache-articles gnus-newsgroup-cached)
+         article)
+      (gnus-cache-change-buffer gnus-newsgroup-name)
+      (while articles
+       (if (memq (setq article (pop articles)) cache-articles)
+           ;; The article was in the cache, so we see whether we are
+           ;; supposed to remove it from the cache.
+           (gnus-cache-possibly-remove-article
+            article (memq article gnus-newsgroup-marked)
+            (memq article gnus-newsgroup-dormant)
+            (or (memq article gnus-newsgroup-unreads)
+                (memq article gnus-newsgroup-unselected))))))
+    ;; The overview file might have been modified, save it
+    ;; safe because we're only called at group exit anyway.
+    (gnus-cache-save-buffers)))
 
 (defun gnus-cache-request-article (article group)
   "Retrieve ARTICLE in GROUP from the cache."
@@ -206,16 +210,18 @@ variable to \"^nnml\".")
         (> (cdr cache-active) (cdr active))
         (setcdr active (cdr cache-active)))))
 
-(defun gnus-cache-retrieve-headers (articles group)
+(defun gnus-cache-retrieve-headers (articles group &optional fetch-old)
   "Retrieve the headers for ARTICLES in GROUP."
-  (let* ((cached (gnus-cache-articles-in-group group))
+  (let* ((cached 
+         (setq gnus-newsgroup-cached (gnus-cache-articles-in-group group)))
         (articles (gnus-sorted-complement articles cached))
         (cache-file (gnus-cache-file-name group ".overview"))
         type)
     ;; We first retrieve all the headers that we don't have in 
     ;; the cache.
     (let ((gnus-use-cache nil))
-      (setq type (and articles (gnus-retrieve-headers articles group))))
+      (setq type (and articles 
+                     (gnus-retrieve-headers articles group fetch-old))))
     (gnus-cache-save-buffers)
     ;; Then we insert the cached headers.
     (save-excursion
@@ -240,6 +246,45 @@ variable to \"^nnml\".")
        (gnus-cache-braid-heads group cached)
        type)))))
 
+(defun gnus-cache-enter-article (n)
+  "Enter the next N articles into the cache.
+If not given a prefix, use the process marked articles instead.
+Returns the list of articles entered."
+  (interactive "P")
+  (gnus-set-global-variables)
+  (let ((articles (gnus-summary-work-articles n))
+       article out)
+    (while articles
+      (setq article (pop articles))
+      (when (gnus-cache-possibly-enter-article 
+            gnus-newsgroup-name article (gnus-summary-article-header article)
+            nil nil nil t)
+       (push article out))
+      (gnus-summary-remove-process-mark article)
+      (gnus-summary-update-secondary-mark article))
+    (gnus-summary-position-point)
+    (nreverse out)))
+
+(defun gnus-cache-remove-article (n)
+  "Remove the next N articles from the cache.
+If not given a prefix, use the process marked articles instead.
+Returns the list of articles removed."
+  (interactive "P")
+  (gnus-set-global-variables)
+  (let ((articles (gnus-summary-work-articles n))
+       article out)
+    (while articles
+      (setq article (pop articles))
+      (when (gnus-cache-possibly-remove-article article nil nil nil t)
+       (push article out))
+      (gnus-summary-remove-process-mark article)
+      (gnus-summary-update-secondary-mark article))
+    (gnus-summary-position-point)
+    (nreverse out)))
+
+(defun gnus-cached-article-p (article)
+  "Say whether ARTICLE is cached in the current group."
+  (memq article gnus-newsgroup-cached))
 
 ;;; Internal functions.
 
@@ -285,12 +330,13 @@ variable to \"^nnml\".")
          (if (stringp article) article (int-to-string article))))
 
 (defun gnus-cache-possibly-remove-article 
-  (article ticked dormant unread)
+  (article ticked dormant unread &optional force)
+  "Possibly remove ARTICLE from the cache."
   (let ((file (gnus-cache-file-name gnus-newsgroup-name article)))
-    (if (or (not (file-exists-p file))
-           (not (gnus-cache-member-of-class
-                 gnus-cache-remove-articles ticked dormant unread)))
-       nil
+    (when (and (file-exists-p file)
+              (or force
+                  (gnus-cache-member-of-class
+                   gnus-cache-remove-articles ticked dormant unread)))
       (save-excursion
        (delete-file file)
        (set-buffer (cdr gnus-cache-buffer))
@@ -299,20 +345,19 @@ variable to \"^nnml\".")
                (search-forward (concat "\n" (int-to-string article) "\t")
                                (point-max) t))
            (delete-region (progn (beginning-of-line) (point))
-                          (progn (forward-line 1) (point))))))))
+                          (progn (forward-line 1) (point)))))
+      (setq gnus-newsgroup-cached
+           (delq article gnus-newsgroup-cached))
+      t)))
 
 (defun gnus-cache-articles-in-group (group)
+  "Return a sorted list of cached articles in GROUP."
   (let ((dir (file-name-directory (gnus-cache-file-name group 1)))
        articles)
-    (if (not (file-exists-p dir))
-       nil
-      (setq articles (directory-files dir nil "^[0-9]+$" t))
-      (if (not articles)
-         nil
-       (sort (mapcar (function (lambda (name)
-                                 (string-to-int name))) 
-                     articles)
-             '<)))))
+    (when (file-exists-p dir)
+      (sort (mapcar (lambda (name) (string-to-int name)) 
+                   (directory-files dir nil "^[0-9]+$" t))
+           '<))))
 
 (defun gnus-cache-braid-nov (group cached)
   (let ((cache-buf (get-buffer-create " *gnus-cache*"))
@@ -420,8 +465,9 @@ variable to \"^nnml\".")
       (mapatoms
        (lambda (sym)
         (when (and sym (boundp sym))
-          (insert (symbol-name sym) " " (cdr (symbol-value sym))
-                  " " (car (symbol-value sym)) " y\n")))
+          (insert (format "%s %d %d y\n"
+                          (symbol-name sym) (cdr (symbol-value sym))
+                          (car (symbol-value sym))))))
        gnus-cache-active-hashtb)
       (write-region 
        (point-min) (point-max) gnus-cache-active-file nil 'silent))
@@ -445,6 +491,7 @@ If LOW, update the lower bound instead."
 ;;;###autoload
 (defun gnus-cache-generate-active (&optional directory)
   "Generate the cache active file."
+  (interactive)
   (let* ((top (null directory))
         (directory (or directory (expand-file-name gnus-cache-directory)))
         (files (directory-files directory 'full))
@@ -457,6 +504,7 @@ If LOW, update the lower bound instead."
             ?/ ?.)))
         nums alphs)
     (when top
+      (gnus-message 5 "Generating the cache active file...")
       (setq gnus-cache-active-hashtb (gnus-make-hashtable 123)))
     ;; Separate articles from all other files and directories.
     (while files
@@ -471,13 +519,24 @@ If LOW, update the lower bound instead."
     ;; Go through all the other files.
     (while alphs
       (when (and (file-directory-p (car alphs))
-                (not (string-match "^\\.\\.?$" (file-name-nondirectory (car alphs)))))
+                (not (string-match "^\\.\\.?$"
+                                   (file-name-nondirectory (car alphs)))))
        ;; We descend directories.
        (gnus-cache-generate-active (car alphs)))
       (setq alphs (cdr alphs)))
     ;; Write the new active file.
     (when top
-      (gnus-cache-write-active t))))
+      (gnus-cache-write-active t)
+      (gnus-message 5 "Generating the cache active file...done"))))
+
+;;;###autoload
+(defun gnus-cache-generate-nov-databases (dir)
+  "Generate NOV files recursively starting in DIR."
+  (interactive (list gnus-cache-directory))
+  (gnus-cache-close)
+  (require 'nnml)
+  (let ((nnml-generate-active-function 'identity))
+    (nnml-generate-nov-databases dir)))
 
 (provide 'gnus-cache)
              
index 2ad1c0b..a83bde2 100644 (file)
@@ -65,7 +65,8 @@ less space and be faster as a result.")
                    (summary-highlight 
                     article-highlight 
                     summary-menu group-menu article-menu
-                    browse-menu server-menu))
+                    browse-menu server-menu
+                    page-marker))
                  (name . gnus-visual)
                  (type . toggle))
                 ((tag . "WWW Browser")
index 641683e..77963c0 100644 (file)
@@ -64,18 +64,14 @@ Optional argument FOLDER specifies folder name."
                   t))))
        (errbuf (get-buffer-create " *Gnus rcvstore*"))
        ;; Find the rcvstore program.
-       (rcvstore
-        (expand-file-name
-         (mh-search-path
-          (if mh-lib (cons mh-lib exec-path) exec-path)
-          "rcvstore"))))
+       (exec-path (if mh-lib (cons mh-lib exec-path) exec-path)))
     (gnus-eval-in-buffer-window 
      gnus-original-article-buffer
      (save-restriction
        (widen)
        (unwind-protect
           (call-process-region 
-           (point-min) (point-max) rcvstore nil errbuf nil folder)
+           (point-min) (point-max) "rcvstore" nil errbuf nil folder)
         (set-buffer errbuf)
         (if (zerop (buffer-size))
             (message "Article saved in folder: %s" folder)
index 8d997d5..64e1692 100644 (file)
@@ -530,7 +530,7 @@ Type \\[describe-mode] in the buffer to get a list of commands."
   "Return non-nil if GROUP (and ARTICLE) come from a news server."
   (or (gnus-member-of-valid 'post group) ; Ordinary news group.
       (and (gnus-member-of-valid 'post-mail group) ; Combined group.
-          (eq (gnus-request-type group article) 'post))))
+          (eq (gnus-request-type group article) 'news))))
           
 (defun gnus-inews-news (&optional use-group-method)
   "Send a news message.
@@ -1553,7 +1553,7 @@ Customize the variable gnus-mail-forward-method to use another mailer."
   (interactive "sResend message to: ")
   (gnus-summary-select-article)
   (save-excursion
-    (let (resent)
+    (let (resent beg)
       ;; We first set up a normal mail buffer.
       (nnheader-set-temp-buffer " *Gnus resend*")
       ;; This code from sendmail.el
@@ -1565,8 +1565,7 @@ Customize the variable gnus-mail-forward-method to use another mailer."
       (insert mail-header-separator "\n")
       ;; Insert our usual headers.
       (gnus-inews-narrow-to-headers)
-      (let ((headers '(From Date To)))
-       (gnus-inews-insert-headers headers))
+      (gnus-inews-insert-headers '(From Date To))
       (goto-char (point-min))
       ;; Rename them all to "Resent-*".
       (while (re-search-forward "^[A-Za-z]" nil t)
@@ -1575,12 +1574,17 @@ Customize the variable gnus-mail-forward-method to use another mailer."
       (widen)
       (forward-line)
       (delete-region (point) (point-max))
+      (setq beg (point))
       ;; Insert the message to be resent.
       (insert-buffer-substring gnus-original-article-buffer)
       (goto-char (point-min))
       (search-forward "\n\n")
       (forward-char -1)
       (insert mail-header-separator)
+      ;; Rename all old ("Also-")Resent headers.
+      (while (re-search-backward "^\\(Also-\\)?Resent-" beg t)
+       (beginning-of-line)
+       (insert "Also-"))
       ;; Send it.
       (mail-send)
       (kill-buffer (current-buffer)))))
@@ -1628,6 +1632,7 @@ mailer."
     (pop-to-buffer gnus-mail-buffer)
     (erase-buffer)
     (gnus-mail-setup 'new to subject)
+    (gnus-inews-insert-gcc)
     (run-hooks 'gnus-mail-hook)))
 
 (defun gnus-mail-reply (&optional yank to-address followup)
@@ -1739,6 +1744,7 @@ mailer."
        (setq gnus-in-reply-to message-of)
 
        (auto-save-mode auto-save-default)
+       (gnus-inews-insert-gcc)
 
        (if (and follow-to (listp follow-to))
            (progn
@@ -1821,6 +1827,7 @@ If INHIBIT-PROMPT, never prompt for a Subject."
     (insert "\n\n")
 
     (gnus-inews-insert-bfcc)
+    (gnus-inews-insert-gcc)
     (gnus-inews-insert-signature)
     (and gnus-post-prepare-function
         (gnus-functionp gnus-post-prepare-function)
@@ -1981,7 +1988,8 @@ If INHIBIT-PROMPT, never prompt for a Subject."
                  (insert to))))
 
          (gnus-inews-insert-bfcc)
-
+         (gnus-inews-insert-gcc)
+    
          ;; Now the headers should be ok, so we do the yanking.
          (goto-char (point-min))
          (re-search-forward
@@ -2449,17 +2457,20 @@ Headers will be generated before sending."
       (insert gnus-author-copy))))
 
 (defun gnus-inews-insert-gcc ()
-  (let* ((group gnus-outgoing-message-group)
-        (gcc (cond 
-              ((gnus-functionp group)
-               (funcall group))
-              ((or (stringp group) (list group))
-               group))))
-    (when gcc
-      (insert "Gcc: "
-             (if (stringp group) group
-               (mapconcat 'identity group " "))
-             "\n"))))
+  (save-excursion
+    (save-restriction
+      (gnus-inews-narrow-to-headers)
+      (let* ((group gnus-outgoing-message-group)
+            (gcc (cond 
+                  ((gnus-functionp group)
+                   (funcall group))
+                  ((or (stringp group) (list group))
+                   group))))
+       (when gcc
+         (insert "Gcc: "
+                 (if (stringp group) group
+                   (mapconcat 'identity group " "))
+                 "\n"))))))
 
 ;;; Handling rejected (and postponed) news.
 
index 040a3f6..2f27b90 100644 (file)
@@ -693,6 +693,9 @@ SCORE is the score to add."
          (exclude-files (gnus-score-get 'exclude-files alist))
           (orphan (car (gnus-score-get 'orphan alist)))
          (adapt (gnus-score-get 'adapt alist))
+         (thread-mark-and-expunge
+          (car (gnus-score-get 'thread-mark-and-expunge alist)))
+         (adapt-file (car (gnus-score-get 'adapt-file)))
          (local (gnus-score-get 'local alist))
          (eval (car (gnus-score-get 'eval alist))))
       ;; We do not respect eval and files atoms from global score
@@ -701,7 +704,8 @@ SCORE is the score to add."
           (setq lists (apply 'append lists
                              (mapcar (lambda (file)
                                        (gnus-score-load-file file)) 
-                                     files))))
+                                     (if adapt-file (cons adapt-file files)
+                                       files)))))
       (and eval (not global) (eval eval))
       ;; We then expand any exclude-file directives.
       (setq gnus-scores-exclude-files 
@@ -734,10 +738,14 @@ SCORE is the score to add."
                  (t
                   ;;(setq gnus-newsgroup-adaptive gnus-use-adaptive-scoring)
                   gnus-default-adaptive-score-alist)))
+      (setq gnus-thread-expunge-below 
+           (or thread-mark-and-expunge gnus-thread-expunge-below))
       (setq gnus-summary-mark-below 
            (or mark mark-and-expunge gnus-summary-mark-below))
       (setq gnus-summary-expunge-below 
-           (or expunge mark-and-expunge gnus-summary-expunge-below)))
+           (or expunge mark-and-expunge gnus-summary-expunge-below))
+      (setq gnus-newsgroup-adaptive-score-file 
+           (or adapt-file gnus-newsgroup-adaptive-score-file)))
     (setq gnus-current-score-file file)
     (setq gnus-score-alist alist)
     lists))
@@ -1597,8 +1605,10 @@ SCORE is the score to add."
          (setq elem (cdr elem)))
        (setq malist (cdr malist)))
       ;; We change the score file to the adaptive score file.
-      (gnus-score-load-file (gnus-score-file-name 
-                            gnus-newsgroup-name gnus-adaptive-file-suffix))
+      (gnus-score-load-file 
+       (or gnus-newsgroup-adaptive-score-file
+          (gnus-score-file-name 
+           gnus-newsgroup-name gnus-adaptive-file-suffix)))
       ;; The we score away.
       (while data
        (setq elem (cdr (assq (gnus-data-mark (car data)) alist)))
@@ -1837,46 +1847,46 @@ GROUP using BNews sys file syntax."
        (insert (car sfiles))
        (goto-char (point-min))
        ;; First remove the suffix itself.
-       (re-search-forward (concat "." score-regexp))
-       (replace-match "" t t) 
-       (goto-char (point-min))
-       (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)))
-       ;; If short file names were used, we have to translate slashes.
-       (goto-char (point-min))
-       (while (re-search-forward "[/:]" nil t)
-         (replace-match "." t t))
-       ;; Cludge to get rid of "nntp+" problems.
-       (goto-char (point-min))
-       (and (looking-at "nn[a-z]+\\+")
-            (progn
-              (search-forward "+")
-              (forward-char -1)
-              (insert "\\")))
-       ;; Translate "all" to ".*".
-       (while (search-forward "all" nil t)
-         (replace-match ".*" t t))
-       (goto-char (point-min))
-       ;; 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)
-                    (string-match regexp group)))
-           (setq ofiles (cons (car sfiles) ofiles)))
+       (when (re-search-forward (concat "." score-regexp) nil t)
+         (replace-match "" t t) 
+         (goto-char (point-min))
+         (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)))
+         ;; If short file names were used, we have to translate slashes.
+         (goto-char (point-min))
+         (while (re-search-forward "[/:]" nil t)
+           (replace-match "." t t))
+         ;; Cludge to get rid of "nntp+" problems.
+         (goto-char (point-min))
+         (and (looking-at "nn[a-z]+\\+")
+              (progn
+                (search-forward "+")
+                (forward-char -1)
+                (insert "\\")))
+         ;; Translate "all" to ".*".
+         (while (search-forward "all" nil t)
+           (replace-match ".*" t t))
+         (goto-char (point-min))
+         ;; 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)
+                      (string-match regexp group)))
+             (setq ofiles (cons (car sfiles) ofiles))))
        (setq sfiles (cdr sfiles)))
       (kill-buffer (current-buffer))
       ;; Slight kludge here - the last score file returned should be
index e2b7bf1..1bd1fdd 100644 (file)
@@ -241,11 +241,11 @@ If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
     (add-text-properties 
      (point)
      (prog1 (1+ (point)) 
-       (eval gnus-topic-line-format-spec))
+       (eval gnus-topic-line-format-spec)
+       (gnus-group-remove-excess-properties))
      (list 'gnus-topic name
           'gnus-topic-level level
-          'gnus-topic-visible visiblep))
-    (gnus-group-remove-excess-properties)))
+          'gnus-topic-visible visiblep))))
 
 (defun gnus-topic-previous-topic (topic)
   "Return the previous topic on the same level as TOPIC."
@@ -526,22 +526,47 @@ group."
 (defun gnus-topic-kill-group (&optional n discard)
   "Kill the next N groups."
   (interactive "P")
-  (if (not (gnus-group-topic-p))
-      (gnus-group-kill-group n discard)
-    (let ((topic (gnus-group-topic-name)))
-      (gnus-topic-remove-topic nil t)
-      (push (gnus-topic-find-topology topic nil nil gnus-topic-topology)
-           gnus-topic-killed-topics))))
+  (if (gnus-group-topic-p)
+      (let ((topic (gnus-group-topic-name)))
+       (gnus-topic-remove-topic nil t)
+       (push (gnus-topic-find-topology topic nil nil gnus-topic-topology)
+             gnus-topic-killed-topics))
+    ;; We first kill the groups the normal way...
+    (let ((killed (gnus-group-kill-group n discard))
+         group alist)
+      ;; Then we remove the killed groups from the topics they belong to.
+      (when (stringp killed)
+       (setq killed (list killed)))
+      (while killed
+       (when (setq alist (assoc (gnus-group-topic (setq group (pop killed)))
+                                gnus-topic-alist))
+         (setcdr alist (delete group (cdr alist))))))))
   
 (defun gnus-topic-yank-group (&optional arg)
   "Yank the last topic."
   (interactive "p")
-  (if (null gnus-topic-killed-topics)
-      (gnus-group-yank-group arg)
-    (let ((previous (gnus-group-parent-topic))
-         (item (nth 1 (pop gnus-topic-killed-topics))))
-      (gnus-topic-create-topic
-       (car item) (gnus-topic-parent-topic previous) previous))))
+  (if gnus-topic-killed-topics
+      (let ((previous (gnus-group-parent-topic))
+           (item (nth 1 (pop gnus-topic-killed-topics))))
+       (gnus-topic-create-topic
+        (car item) (gnus-topic-parent-topic previous) previous))
+    ;; We first yank the groups the normal way...
+    (let* ((topic (gnus-group-parent-topic))
+          (prev (gnus-group-group-name))
+          (alist (assoc topic gnus-topic-alist))
+          (yanked (gnus-group-yank-group arg))
+          group)
+      ;; Then we enter the yanked groups in the topics they belong to.
+      (when (stringp yanked)
+       (setq yanked (list yanked)))
+      (if (not prev)
+         (nconc alist yanked)
+       (setq alist (cdr alist))
+       (while (cdr alist)
+         (when (equal (car (cdr alist)) prev)
+           (setcdr alist (nconc yanked (cdr alist)))
+           (setq alist nil))
+         (setq alist (cdr alist)))))))
 
 (defun gnus-topic-hide-topic ()
   "Hide all subtopics under the current topic."
index cff62d9..85267aa 100644 (file)
@@ -633,7 +633,8 @@ The headers will be included in the sequence they are matched.")
       (setq files (gnus-uu-unpack-files files)))
     (gnus-uu-add-file (mapcar (lambda (file) (cdr (assq 'name file))) files))
     (setq files (nreverse (gnus-uu-get-actions files)))
-    (or not-insert (gnus-summary-insert-pseudos files save))))
+    (or not-insert (not gnus-insert-pseudo-articles)
+       (gnus-summary-insert-pseudos files save))))
 
 ;; Return a list of files in dir.
 (defun gnus-uu-scan-directory (dir)
index 765a851..e8dd002 100644 (file)
@@ -956,8 +956,8 @@ If nil, the user will be asked for a duration.")
         (end (progn (end-of-line) (point)))
         ;; now find out where the line starts and leave point there.
         (beg (progn (beginning-of-line) (point)))
-        (score (or (cdr (assq (or (gnus-summary-article-number)
-                                  gnus-current-article)
+        (article (gnus-summary-article-number))
+        (score (or (cdr (assq (or article gnus-current-article)
                               gnus-newsgroup-scored))
                    gnus-summary-default-score 0))
         (default gnus-summary-default-score)
@@ -1179,20 +1179,31 @@ call it with the value of the `gnus-data' text property."
         (fun (get-text-property (point) 'gnus-callback)))
     (if fun (funcall fun data))))
 
-;; Suggested by Arne Elofsson <arne@hodgkin.mbi.ucla.edu>
-(defun gnus-article-next-button ()
-  "Move point to next button."
-  (interactive)
-  (if (get-text-property (point) 'gnus-callback)
-      (goto-char (next-single-property-change (point) 'gnus-callback
-                                             nil (point-max))))
-  (let ((pos (next-single-property-change (point) 'gnus-callback)))
-    (if pos
-       (goto-char pos)
-      (setq pos (next-single-property-change (point-min) 'gnus-callback))
-      (if pos
-         (goto-char pos)
-       (error "No buttons found")))))
+(defun gnus-article-prev-button (n)
+  "Move point to N buttons backward.
+If N is negative, move forward instead."
+  (interactive "p")
+  (gnus-article-next-button (- n)))
+
+(defun gnus-article-next-button (n)
+  "Move point to N buttons forward.
+If N is negative, move backward instead."
+  (interactive "p")
+  (let ((function (if (< n 0) 'prev-single-property-change
+                   'next-single-property-change))
+       (limit (if (< n 0) (point-min) (point-max))))
+    (setq n (abs n))
+    (while (and (not (= limit (point)))
+               (> n 0))
+      ;; Skip past the current button.
+      (when (get-text-property (point) 'gnus-callback)
+       (goto-char (funcall function (point) 'gnus-callback nil limit)))
+      ;; Go to the next (or previous) button.
+      (funcall function (point) 'gnus-callback nil limit)
+      (decf n))
+    (unless (zerop n)
+      (gnus-message 5 "No more buttons"))
+    n))
 
 (defun gnus-article-highlight (&optional force)
   "Highlight current article.
@@ -1467,6 +1478,33 @@ specified by `gnus-button-alist'."
   "Browse ADDRESS."
   (funcall browse-url-browser-function address))
 
+;;; Next/prev buttons in the article buffer.
+
+(defvar gnus-next-page-line-format "%{%(Next page...%)%}\n")
+(defvar gnus-prev-page-line-format "%{%(Previous page...%)%}\n")
+
+(defvar gnus-prev-page-map nil)
+(unless gnus-prev-page-map
+  (setq gnus-prev-page-map (make-sparse-keymap))
+  (define-key gnus-prev-page-map "\n" 'gnus-article-prev-page))
+
+(defun gnus-insert-prev-page-button ()
+  (let ((buffer-read-only nil))
+    (gnus-remove-text-with-property 'gnus-prev)
+    (gnus-eval-format gnus-prev-page-line-format nil
+                     `(gnus-prev t local-map ,gnus-prev-page-map))))
+
+(defvar gnus-next-page-map nil)
+(unless gnus-next-page-map
+  (setq gnus-next-page-map (make-sparse-keymap))
+  (define-key gnus-next-page-map "\n" 'gnus-article-next-page))
+
+(defun gnus-insert-next-page-button ()
+  (let ((buffer-read-only nil))
+    (gnus-remove-text-with-property 'gnus-next)
+    (gnus-eval-format gnus-next-page-line-format nil
+                     `(gnus-next t local-map ,gnus-next-page-map))))
+
 ;;; Compatibility Functions:
 
 (or (fboundp 'rassoc)
index 906ed4f..50b51ae 100644 (file)
@@ -224,6 +224,15 @@ call it with the value of the `gnus-data' text property."
   (easy-menu-add gnus-article-article-menu)
   (easy-menu-add gnus-article-treatment-menu))
 
+(defun gnus-xmas-read-event-char ()
+  "Get the next event."
+  (let ((event (next-event)))
+    (while (timeout-event-p event)
+      (setq event (next-event)))
+    (cons (and (key-press-event-p event) 
+              (numberp (event-key event))
+              (event-to-character event)) 
+         event)))
 
 (defun gnus-xmas-define ()
   (setq gnus-mouse-2 [button2])
@@ -244,7 +253,6 @@ call it with the value of the `gnus-data' text property."
   (fset 'set-text-properties 'gnus-xmas-set-text-properties)
 
   (or (boundp 'standard-display-table) (setq standard-display-table nil))
-  (or (boundp 'read-event) (fset 'read-event 'next-command-event))
 
   (defvar gnus-mouse-face-prop 'highlight)
 
@@ -302,8 +310,7 @@ pounce directly on the real variables themselves.")
 
 
 (defun gnus-xmas-redefine ()
-
-
+  "Redefine lots of Gnus functions for XEmacs."
   (fset 'gnus-summary-make-display-table (lambda () nil))
   (fset 'gnus-visual-turn-off-edit-menu 'identity)
   (fset 'gnus-highlight-selected-summary
@@ -316,6 +323,8 @@ pounce directly on the real variables themselves.")
   (fset 'gnus-article-add-button 'gnus-xmas-article-add-button)
   (fset 'gnus-window-top-edge 'gnus-xmas-window-top-edge)
   (fset 'set-text-properties 'gnus-xmas-set-text-properties)
+  (fset 'gnus-read-event-char 'gnus-xmas-read-event-char)
+  (fset 'gnus-group-startup-message 'gnus-xmas-group-startup-message)
 
   (or (fboundp 'appt-select-lowest-window)
       (fset 'appt-select-lowest-window 
@@ -349,56 +358,75 @@ pounce directly on the real variables themselves.")
            (setq path (cdr path))))
        gnus-xmas-glyph-directory)))
 
-(defun gnus-xmas-group-startup (&optional x y)
+(defun gnus-xmas-group-startup-message (&optional x y)
   "Insert startup message in current buffer."
   ;; Insert the message.
+  (gnus-xmas-find-glyph-directory)
   (erase-buffer)
-  (if (featurep 'xpm)
-      (progn
-       (set-glyph-property gnus-xmas-logo 'image  "~/tmp/gnus.xpm")
-       (set-glyph-image gnus-xmas-logo "~/tmp/gnus.xpm" 'global 'x)
-
-       (insert " ")
-       (set-extent-begin-glyph (make-extent (point) (point)) gnus-xmas-logo)
-       (insert "
-   Gnus * A newsreader for Emacsen
- A Praxis Release * larsi@ifi.uio.no")
-       (goto-char (point-min))
-       (while (not (eobp))
-         (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2)
-                              ? ))
-         (forward-line 1))
-       (goto-char (point-min))
-       ;; +4 is fuzzy factor.
-       (insert-char ?\n (/ (max (- (window-height) (or y 24)) 0) 2)))
-
-    (insert
-     (format "
-     %s
-           A newsreader 
-      for GNU Emacs
-
-        Based on GNUS 
-             written by 
-     Masanobu UMEDA
-
-       A Praxis Release
-      larsi@ifi.uio.no
+  (let ((file (and gnus-xmas-glyph-directory
+                  (concat 
+                   (file-name-as-directory gnus-xmas-glyph-directory)
+                   "gnus.xpm"))))
+    (if (and (featurep 'xpm)
+            file (file-exists-p file))
+       (progn
+         (set-glyph-property gnus-xmas-logo 'image file)
+         (set-glyph-image gnus-xmas-logo file 'global 'x)
+
+         (insert " ")
+         (set-extent-begin-glyph (make-extent (point) (point)) gnus-xmas-logo)
+         (goto-char (point-min))
+         (while (not (eobp))
+           (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2)
+                                ? ))
+           (forward-line 1))
+         (goto-char (point-min))
+         (let* ((pheight (+ 20 (count-lines (point-min) (point-max))))
+                (wheight (window-height))
+                (rest (- wheight pheight)))
+           (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
+
+      (insert
+       (format "              %s
+          _    ___ _             _      
+          _ ___ __ ___  __    _ ___     
+          __   _     ___    __  ___     
+              _           ___     _     
+             _  _ __             _      
+             ___   __            _      
+                   __           _       
+                    _      _   _        
+                   _      _    _        
+                      _  _    _         
+                  __  ___               
+                 _   _ _     _          
+                _   _                   
+              _    _                    
+             _    _                     
+            _                         
+          __                             
+
 " 
-            gnus-version))
-    ;; And then hack it.
-    ;; 18 is the longest line.
-    (indent-rigidly (point-min) (point-max) 
-                   (/ (max (- (window-width) (or x 28)) 0) 2))
+              ""))
+      ;; And then hack it.
+      (gnus-indent-rigidly (point-min) (point-max) 
+                          (/ (max (- (window-width) (or x 46)) 0) 2))
+      (goto-char (point-min))
+      (forward-line 1)
+      (let* ((pheight (count-lines (point-min) (point-max)))
+            (wheight (window-height))
+            (rest (- wheight pheight)))
+       (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
+    ;; Fontify some.
+    (goto-char (point-min))
+    (and (search-forward "Praxis" nil t)
+        (put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
     (goto-char (point-min))
-    ;; +4 is fuzzy factor.
-    (insert-char ?\n (/ (max (- (window-height) (or y 12)) 0) 2)))
-
-  ;; Fontify some.
-  (goto-char (point-min))
-  (search-forward "Praxis")
-  (put-text-property (match-beginning 0) (match-end 0) 'face 'bold)
-  (goto-char (point-min)))
+    (let* ((mode-string (gnus-group-set-mode-line)))
+      (setq mode-line-buffer-identification 
+           (list (concat gnus-version (substring (car mode-string) 4))))
+      (set-buffer-modified-p t))))
+
 
 ;;; The toolbar.
 
index f496629..1b8c66d 100644 (file)
@@ -254,6 +254,11 @@ saved will be used.")
 (defvar gnus-asynchronous nil
   "*If non-nil, Gnus will supply backends with data needed for async article fetching.")
 
+(defvar gnus-kill-summary-on-exit t
+  "*If non-nil, kill the summary buffer when you exit from it.
+If nil, the summary will become a \"*Dead Summary*\" buffer, and
+it will be killed sometime later.")
+
 (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 this value,
@@ -320,16 +325,27 @@ The function is called with NEWSGROUP, HEADERS, and optional LAST-FOLDER.")
 The function is called with NEWSGROUP, HEADERS, and optional
 LAST-FILE.")
 
-(defvar gnus-split-methods nil
+(defvar gnus-split-methods 
+  '((gnus-article-archive-name))
   "*Variable used to suggest where articles are to be saved.
-The syntax of this variable is the same as `nnmail-split-methods'.  
-
 For instance, if you would like to save articles related to Gnus in
 the file \"gnus-stuff\", and articles related to VM in \"vm-stuff\",
 you could set this variable to something like:
 
  '((\"^Subject:.*gnus\\|^Newsgroups:.*gnus\" \"gnus-stuff\")
-   (\"^Subject:.*vm\\|^Xref:.*vm\" \"vm-stuff\"))")
+   (\"^Subject:.*vm\\|^Xref:.*vm\" \"vm-stuff\"))
+
+This variable is an alist where the where the key is the match and the
+value is a list of possible files to save in if the match is non-nil.
+
+If the match is a string, it is used as a regexp match on the
+article.  If the match is a symbol, that symbol will be funcalled  
+from the buffer of the article to be saved with the newsgroup as the
+parameter.  If it is a list, it will be evaled in the same buffer.
+
+If this form or function returns a string, this string will be used as
+a possible file name; and if it returns a non-nil list, that list will
+be used as possible file names.")
 
 (defvar gnus-save-score nil
   "*If non-nil, save group scoring info.")
@@ -338,7 +354,10 @@ you could set this variable to something like:
   "*If non-nil, use some adaptive scoring scheme.")
 
 (defvar gnus-use-cache nil
-  "*If non-nil, Gnus will cache (some) articles locally.")
+  "*If nil, Gnus will ignore the article cache.
+If `passive', it will allow entering (and reading) articles
+explicitly entered into the cache.  If anything else, use the
+cache to the full extent of the law.")
 
 (defvar gnus-keep-backlog nil
   "*If non-nil, Gnus will keep read articles for later re-retrieval.
@@ -514,6 +533,11 @@ less than this variable, are subscribed.")
 (defvar gnus-level-default-unsubscribed 6
   "*New unsubscribed groups will be unsubscribed at this level.")
 
+(defvar gnus-activate-level (1+ gnus-level-subscribed)
+  "*Groups higher than this level won't be activated on startup.
+Setting this variable to something log might save lots of time when
+you have many groups that you aren't interested in.")
+
 (defvar gnus-activate-foreign-newsgroups 4
   "*If nil, Gnus will not check foreign newsgroups at startup.
 If it is non-nil, it should be a number between one and nine.  Foreign
@@ -654,10 +678,12 @@ thus making them effectively non-existent.")
 (defvar gnus-ignored-headers
   "^Path:\\|^Posting-Version:\\|^Article-I.D.:\\|^Expires:\\|^Date-Received:\\|^References:\\|^Control:\\|^Xref:\\|^Lines:\\|^Posted:\\|^Relay-Version:\\|^Message-ID:\\|^Nf-ID:\\|^Nf-From:\\|^Approved:\\|^Sender:\\|^Received:\\|^Mail-from:"
   "*All headers that match this regexp will be hidden.
+This variable can also be a list of regexps of headers to be ignored.
 If `gnus-visible-headers' is non-nil, this variable will be ignored.")
 
 (defvar gnus-visible-headers "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Resent-"
   "*All headers that do not match this regexp will be hidden.
+This variable can also be a list of regexp of headers to remain visible.
 If this variable is non-nil, `gnus-ignored-headers' will be ignored.")
 
 (defvar gnus-sorted-header-list
@@ -820,7 +846,7 @@ 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.")
+for your decision; `gnus-subscribe-killed' kills all new groups.")
 
 ;; Suggested by a bug report by Hallvard B Furuseth.
 ;; <h.b.furuseth@usit.uio.no>. 
@@ -884,6 +910,10 @@ list.")
   "*Mark used for articles that are caught up.")
 (defvar gnus-replied-mark ?A
   "*Mark used for articles that have been replied to.")
+(defvar gnus-cached-mark ?*
+  "*Mark used for articles that are in the cache.")
+(defvar gnus-saved-mark ?S
+  "*Mark used for articles that have been saved to.")
 (defvar gnus-process-mark ?# 
   "*Process mark.")
 (defvar gnus-ancient-mark ?O
@@ -912,6 +942,9 @@ will not be asked to confirm the command.")
 If nil, all files that use the same viewing command will be given as a
 list of parameters to that command.")
 
+(defvar gnus-insert-pseudo-articles t
+  "*If non-nil, insert pseudo-articles when decoding articles.")
+
 (defvar gnus-group-line-format "%M%S%p%P%5y: %(%g%)\n"
   "*Format of group lines.
 It works along the same lines as a normal formatting string,
@@ -1023,14 +1056,37 @@ with some simple extensions.
 
 %S  The subject")
 
-(defvar gnus-summary-mode-line-format "Gnus  %G/%A %Z"
-  "*The format specification for the summary mode line.")
-
-(defvar gnus-article-mode-line-format "Gnus  %G/%A %S"
-  "*The format specification for the article mode line.")
+(defvar gnus-summary-mode-line-format "Gnus: %%b [%A] %Z"
+  "*The format specification for the summary mode line.
+It works along the same lines as a normal formatting string,
+with some simple extensions:
+
+%G  Group name
+%p  Unprefixed group name
+%A  Current article number
+%V  Gnus version
+%U  Number of unread articles in the group
+%e  Number of unselected articles in the group
+%Z  A string with unread/unselected article counts
+%g  Shortish group name
+%S  Subject of the current article
+%u  User-defined spec
+%s  Current score file name
+%d  Number of dormant articles
+%r  Number of articles that have been marked as read in this session
+%E  Number of articles expunged by the score files")
+
+(defvar gnus-article-mode-line-format "Gnus: %%b %S"
+  "*The format specification for the article mode line.
+See `gnus-summary-mode-line-format' for a closer description.")
+
+(defvar gnus-group-mode-line-format "Gnus: %%b {%M:%S}"
+  "*The format specification for the group mode line.
+It works along the same lines as a normal formatting string,
+with some simple extensions:
 
-(defvar gnus-group-mode-line-format "Gnus  List of groups   {%M:%S}  "
-  "*The format specification for the group mode line.")
+%S   The native news server.
+%M   The native select method.")
 
 (defvar gnus-valid-select-methods
   '(("nntp" post address prompt-address)
@@ -1062,7 +1118,7 @@ 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 25
+(defvar gnus-mode-non-string-length nil
   "*Max length of mode-line non-string contents.
 If this is nil, Gnus will take space as is needed, leaving the rest
 of the modeline intact.")
@@ -1077,6 +1133,9 @@ of the modeline intact.")
 This variable is local to each summary buffer and usually set by the
 score file.")  
 
+(defvar gnus-article-sort-functions '(gnus-article-sort-by-number)
+  "*List of functions used for sorting articles in the summary buffer.")
+
 (defvar gnus-thread-sort-functions '(gnus-thread-sort-by-number)
   "*List of functions used for sorting threads in the summary buffer.
 By default, threads are sorted by article number.
@@ -1098,6 +1157,14 @@ subthread and should then return the score of the thread.
 
 Some functions you can use are `+', `max', or `min'.")
 
+(defvar gnus-summary-expunge-below nil
+  "All articles that have a score less than this variable will be expunged.")
+
+(defvar gnus-thread-expunge-below nil
+  "All threads that have a total score less than this variable will be expunged.
+See `gnus-thread-score-function' for en explanation of what a 
+\"thread score\" is.")
+
 (defvar gnus-auto-subscribed-groups 
   "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
   "*All new groups that match this regexp will be subscribed automatically.
@@ -1318,6 +1385,7 @@ automatically when it is selected.")
 
 (defvar gnus-inhibit-hiding nil)
 (defvar gnus-topic-indentation "")
+(defvar gnus-inhibit-limiting nil)
 
 (defvar gnus-article-mode-map nil)
 (defvar gnus-dribble-buffer nil)
@@ -1329,6 +1397,7 @@ automatically when it is selected.")
 (defvar gnus-nocem-hashtb nil)
 
 (defvar gnus-current-score-file nil)
+(defvar gnus-newsgroup-adaptive-score-file nil)
 (defvar gnus-scores-exclude-files nil)
 
 (defvar gnus-opened-servers nil)
@@ -1344,7 +1413,7 @@ automatically when it is selected.")
 (defvar gnus-summary-display-table nil)
 
 (defconst gnus-group-line-format-alist
-  `((?M gnus-tmp-marked ?c)
+  `((?M gnus-tmp-marked-mark ?c)
     (?S gnus-tmp-subscribed ?c)
     (?L gnus-tmp-level ?d)
     (?N gnus-tmp-number ?s)
@@ -1428,6 +1497,9 @@ variable (string, integer, character, etc).")
       (?E gnus-newsgroup-expunged-tally ?d)
       (?s (gnus-current-score-file-nondirectory) ?s))))
 
+(defconst gnus-article-mode-line-format-alist  
+  gnus-summary-mode-line-format-alist)
+
 (defconst gnus-group-mode-line-format-alist 
   (` ((?S gnus-tmp-news-server ?s)
       (?M gnus-tmp-news-method ?s)
@@ -1439,7 +1511,7 @@ variable (string, integer, character, etc).")
   "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
   "The mail address of the Gnus maintainers.")
 
-(defconst gnus-version "September Gnus v0.21"
+(defconst gnus-version "September Gnus v0.22"
   "Version number for this version of Gnus.")
 
 (defvar gnus-info-nodes
@@ -1568,6 +1640,12 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (defvar gnus-newsgroup-killed nil
   "List of ranges of articles that have been through the scoring process.")
 
+(defvar gnus-newsgroup-cached nil
+  "List of articles that come from the article cache.")
+
+(defvar gnus-newsgroup-saved nil
+  "List of articles that have been saved.")
+
 (defvar gnus-newsgroup-kill-headers nil)
 
 (defvar gnus-newsgroup-replied nil
@@ -1613,7 +1691,6 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (defvar gnus-summary-mark-positions nil)
 (defvar gnus-group-mark-positions nil)
 
-(defvar gnus-summary-expunge-below nil)
 (defvar gnus-reffed-article-number nil)
 
 ;;; Let the byte-compiler know that we know about this variable.
@@ -1621,6 +1698,8 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 
 (defvar gnus-cache-removeable-articles nil)
 
+(defvar gnus-dead-summary nil)
+
 (defconst gnus-summary-local-variables 
   '(gnus-newsgroup-name 
     gnus-newsgroup-begin gnus-newsgroup-end 
@@ -1628,7 +1707,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
     gnus-newsgroup-last-folder gnus-newsgroup-last-file 
     gnus-newsgroup-auto-expire gnus-newsgroup-unreads 
     gnus-newsgroup-unselected gnus-newsgroup-marked
-    gnus-newsgroup-reads
+    gnus-newsgroup-reads gnus-newsgroup-saved
     gnus-newsgroup-replied gnus-newsgroup-expirable
     gnus-newsgroup-processable gnus-newsgroup-killed
     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
@@ -1643,8 +1722,9 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
     gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files
     gnus-newsgroup-history gnus-newsgroup-ancient
     (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
+    gnus-newsgroup-adaptive-score-file
     (gnus-newsgroup-expunged-tally . 0)
-    gnus-cache-removeable-articles
+    gnus-cache-removeable-articles gnus-newsgroup-cached
     gnus-newsgroup-data gnus-newsgroup-data-reverse
     gnus-newsgroup-limit gnus-newsgroup-limits)
   "Variables that are buffer-local to the summary buffers.")
@@ -1715,14 +1795,15 @@ Thank you for your help in stamping out bugs.
       gnus-server-make-menu-bar gnus-article-make-menu-bar
       gnus-browse-make-menu-bar gnus-highlight-selected-summary
       gnus-summary-highlight-line gnus-carpal-setup-buffer
-      gnus-article-add-button)
+      gnus-article-add-button gnus-insert-next-page-button
+      gnus-insert-prev-page-button)
      ("gnus-vis" :interactive t
       gnus-article-push-button gnus-article-press-button 
       gnus-article-highlight gnus-article-highlight-some 
       gnus-article-hide gnus-article-hide-signature 
       gnus-article-highlight-headers gnus-article-highlight-signature 
       gnus-article-add-buttons gnus-article-add-buttons-to-head 
-      gnus-article-next-button)
+      gnus-article-next-button gnus-article-prev-button)
      ("gnus-demon" gnus-demon-add-nocem gnus-demon-add-scanmail
       gnus-demon-add-disconnection gnus-demon-add-handler
       gnus-demon-remove-handler)
@@ -1739,9 +1820,10 @@ Thank you for your help in stamping out bugs.
      ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers
       gnus-cache-possibly-remove-articles gnus-cache-request-article
       gnus-cache-retrieve-headers gnus-cache-possibly-alter-active
-      gnus-cache-enter-remove-article
+      gnus-cache-enter-remove-article gnus-cached-article-p
       gnus-cache-open gnus-cache-close)
-     ("gnus-cache" :interactive t gnus-jog-cache)
+     ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
+      gnus-cache-remove-article)
      ("gnus-score" :interactive t
       gnus-summary-increase-score gnus-summary-lower-score
       gnus-score-flush-cache gnus-score-close 
@@ -1771,7 +1853,7 @@ Thank you for your help in stamping out bugs.
      ("gnus-msg" (gnus-summary-send-map keymap)
       gnus-mail-yank-original gnus-mail-send-and-exit
       gnus-sendmail-setup-mail gnus-article-mail 
-      gnus-inews-message-id gnus-news-mail gnus-mail-reply)
+      gnus-inews-message-id gnus-new-mail gnus-mail-reply)
      ("gnus-msg" :interactive t
       gnus-group-post-news gnus-group-mail gnus-summary-post-news
       gnus-summary-followup gnus-summary-followup-with-original
@@ -1990,6 +2072,7 @@ Thank you for your help in stamping out bugs.
 (defvar gnus-tmp-subject-or-nil)
 (defvar gnus-tmp-subject)
 (defvar gnus-tmp-marked)
+(defvar gnus-tmp-marked-mark)
 (defvar gnus-tmp-subscribed)
 (defvar gnus-tmp-process-marked)
 (defvar gnus-tmp-number-of-unread)
@@ -2038,7 +2121,7 @@ Thank you for your help in stamping out bugs.
   (gnus-byte-code 'gnus-summary-dummy-line-format-spec))
 
 (defun gnus-group-line-format-spec ()
-  (insert gnus-tmp-marked gnus-tmp-subscribed 
+  (insert gnus-tmp-marked-mark gnus-tmp-subscribed 
          gnus-tmp-process-marked
          gnus-topic-indentation
          (format "%5s: " gnus-tmp-number-of-unread))
@@ -2051,32 +2134,15 @@ Thank you for your help in stamping out bugs.
 (defvar gnus-group-line-format-spec 
   (gnus-byte-code 'gnus-group-line-format-spec))
 
-(defun gnus-summary-mode-line-format-spec ()
-  (format "Gnus  %s/%d %s" gnus-tmp-group-name
-         gnus-tmp-article-number gnus-tmp-unread-and-unselected))
-(defvar gnus-summary-mode-line-format-spec
-  (gnus-byte-code 'gnus-summary-mode-line-format-spec))
-
-(defun gnus-group-mode-line-format-spec ()
-  (format "Gnus  List of groups   {%s:%s}  "
-         gnus-tmp-news-method gnus-tmp-news-server))
-(defvar gnus-group-mode-line-format-spec 
-  (gnus-byte-code 'gnus-group-mode-line-format-spec))
-
-(defun gnus-article-mode-line-format-spec ()
-  (format "Gnus  %s/%d %s" gnus-tmp-group-name
-         gnus-tmp-article-number gnus-tmp-subject))
-(defvar gnus-article-mode-line-format-spec
-  (gnus-byte-code 'gnus-article-mode-line-format-spec))
-
 (defvar gnus-old-specs 
-  '((article-mode . "Gnus  %G/%A %S")
-    (group-mode . "Gnus  List of groups   {%M:%S}  ")
-    (summary-mode . "Gnus  %G/%A %Z")
-    (group . "%M%S%p%5y: %(%g%)\n")
+  '((group . "%M%S%p%5y: %(%g%)\n")
     (summary-dummy . "*  :                          : %S\n")
     (summary . "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n")))
 
+(defvar gnus-article-mode-line-format-spec nil)
+(defvar gnus-summary-mode-line-format-spec nil)
+(defvar gnus-group-mode-line-format-spec nil)
+
 ;;; Phew.  All that gruft is over, fortunately.  
 
 \f
@@ -2328,37 +2394,40 @@ Thank you for your help in stamping out bugs.
       (goto-char (point-min))
       (while (re-search-forward "%[-0-9]*\\(,[0-9]+\\)?\\([^0-9]\\)\\(.\\)?"
                                nil t)
-       (setq spec (string-to-char (match-string 2)))
-       ;; First check if there are any specs that look anything like
-       ;; "%12,12A", ie. with a "max width specification".  These have
-       ;; to be treated specially.
-       (if (setq beg (match-beginning 1))
-           (setq max-width 
-                 (string-to-int 
-                  (buffer-substring (1+ (match-beginning 1)) (match-end 1))))
-         (setq max-width 0)
-         (setq beg (match-beginning 2)))
-       ;; Find the specification from `spec-alist'.
-       (unless (setq elem (cdr (assq spec spec-alist)))
-         (setq elem '("*" ?s)))
-       ;; Treat user defined format specifiers specially.
-       (when (eq (car elem) 'gnus-tmp-user-defined)
-         (setq elem
-               (list 
-                (list (intern (concat "gnus-user-format-function-"
-                                      (match-string 3)))
-                      'gnus-tmp-header) ?s))
-         (delete-region (match-beginning 3) (match-end 3)))
-       (if (not (zerop max-width))
-           (let ((el (car elem)))
-             (cond ((= (car (cdr elem)) ?c) 
-                    (setq el (list 'char-to-string el)))
-                   ((= (car (cdr elem)) ?d)
-                    (numberp el) (setq el (list 'int-to-string el))))
-             (setq flist (cons (gnus-max-width-function el max-width)
-                               flist))
-             (setq newspec ?s))
-         (setq flist (cons (car elem) flist))
+       (if (= (setq spec (string-to-char (match-string 2))) ?%)
+             (setq newspec "%"
+                   beg (1+ (match-beginning 0)))
+         ;; First check if there are any specs that look anything like
+         ;; "%12,12A", ie. with a "max width specification".  These have
+         ;; to be treated specially.
+         (if (setq beg (match-beginning 1))
+             (setq max-width 
+                   (string-to-int 
+                    (buffer-substring 
+                     (1+ (match-beginning 1)) (match-end 1))))
+           (setq max-width 0)
+           (setq beg (match-beginning 2)))
+         ;; Find the specification from `spec-alist'.
+         (unless (setq elem (cdr (assq spec spec-alist)))
+           (setq elem '("*" ?s)))
+         ;; Treat user defined format specifiers specially.
+         (when (eq (car elem) 'gnus-tmp-user-defined)
+           (setq elem
+                 (list 
+                  (list (intern (concat "gnus-user-format-function-"
+                                        (match-string 3)))
+                        'gnus-tmp-header) ?s))
+           (delete-region (match-beginning 3) (match-end 3)))
+         (if (not (zerop max-width))
+             (let ((el (car elem)))
+               (cond ((= (car (cdr elem)) ?c) 
+                      (setq el (list 'char-to-string el)))
+                     ((= (car (cdr elem)) ?d)
+                      (numberp el) (setq el (list 'int-to-string el))))
+               (setq flist (cons (gnus-max-width-function el max-width)
+                                 flist))
+               (setq newspec ?s))
+           (setq flist (cons (car elem) flist)))
          (setq newspec (car (cdr elem))))
        ;; Remove the old specification (and possibly a ",12" string).
        (delete-region beg (match-end 2))
@@ -2411,6 +2480,23 @@ Thank you for your help in stamping out bugs.
            (cons 'insert result)))
       (or (car result) ""))))
 
+(defun gnus-eval-format (format &optional alist props)
+  "Eval the format variable FORMAT, using ALIST.
+If INSERT, insert the result."
+  (let ((form (gnus-parse-format format alist props)))
+    (if props
+       (add-text-properties (point) (progn (eval form) (point)) props)
+      (eval form))))
+
+(defun gnus-remove-text-with-property (prop)
+  "Delete all text in the current buffer with text property PROP."
+  (save-excursion
+    (goto-char (point-min))
+    (while (not (eobp))
+      (when (get-text-property (point) prop)
+       (delete-char 1))
+      (goto-char (next-single-property-change (point) prop nil (point-max))))))
+
 (defun gnus-set-work-buffer ()
   (if (get-buffer gnus-work-buffer)
       (progn
@@ -2580,17 +2666,21 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                  (substring groupkey (match-beginning 1) (match-end 1)))))
       (gnus-subscribe-newsgroup newgroup before))))
 
-(defun gnus-subscribe-interactively (newsgroup)
-  "Subscribe new NEWSGROUP interactively.
+(defun gnus-subscribe-interactively (group)
+  "Subscribe the new GROUP interactively.
 It is inserted in hierarchical newsgroup order if subscribed.  If not,
 it is killed."
-  (if (gnus-y-or-n-p (format "Subscribe new newsgroup: %s " newsgroup))
-      (gnus-subscribe-hierarchically newsgroup)
-    (setq gnus-killed-list (cons newsgroup gnus-killed-list))))
+  (if (gnus-y-or-n-p (format "Subscribe new newsgroup: %s " group))
+      (gnus-subscribe-hierarchically group)
+    (push group gnus-killed-list)))
+
+(defun gnus-subscribe-zombies (group)
+  "Make the new GROUP into a zombie group."
+  (push group gnus-zombie-list))
 
-(defun gnus-subscribe-zombies (newsgroup)
-  "Make new NEWSGROUP a zombie group."
-  (setq gnus-zombie-list (cons newsgroup gnus-zombie-list)))
+(defun gnus-subscribe-killed (group)
+  "Make the new GROUP a killed group."
+  (push group gnus-killed-list))
 
 (defun gnus-subscribe-newsgroup (newsgroup &optional next)
   "Subscribe new NEWSGROUP.
@@ -3530,6 +3620,7 @@ Note: LIST has to be sorted over `<'."
   (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 "\M- " 'gnus-group-unhidden-select-group)
   (define-key gnus-group-mode-map "\r" 'gnus-group-select-group)
   (define-key gnus-group-mode-map "\M-\r" 'gnus-group-quick-select-group)
   (define-key gnus-group-mode-map "j" 'gnus-group-jump-to-group)
@@ -3588,6 +3679,7 @@ Note: LIST has to be sorted over `<'."
   (define-key gnus-group-mode-map "\C-c\C-b" 'gnus-bug)
   (define-key gnus-group-mode-map "\C-c\C-s" 'gnus-group-sort-groups)
   (define-key gnus-group-mode-map "t" 'gnus-topic-mode)
+  (define-key gnus-group-mode-map "\C-c\M-g" 'gnus-activate-all-groups)
 
   (define-key gnus-group-mode-map "#" 'gnus-group-mark-group)
   (define-key gnus-group-mode-map "\M-#" 'gnus-group-unmark-group)
@@ -3662,6 +3754,7 @@ Note: LIST has to be sorted over `<'."
   (define-key gnus-group-sub-map "k" 'gnus-group-kill-group)
   (define-key gnus-group-sub-map "y" 'gnus-group-yank-group)
   (define-key gnus-group-sub-map "w" 'gnus-group-kill-region)
+  (define-key gnus-group-sub-map "\C-k" 'gnus-group-kill-level)
   (define-key gnus-group-sub-map "z" 'gnus-group-kill-all-zombies))
 
 (defun gnus-group-mode ()
@@ -3906,7 +3999,7 @@ This will also compile the user-defined format specs."
   (goto-char (point-min))
   (let* ((mode-string (gnus-group-set-mode-line)))
     (setq mode-line-buffer-identification 
-         (concat gnus-version (substring mode-string 4)))
+         (list (concat gnus-version (substring (car mode-string) 4))))
     (set-buffer-modified-p t)))
 
 (defun gnus-group-startup-message-old (&optional x y)
@@ -4328,7 +4421,7 @@ increase the score of each group you read."
          (if gnus-tmp-method
              (format "(%s:%s)" (car gnus-tmp-method)
                      (car (cdr gnus-tmp-method))) ""))
-        (gnus-tmp-marked 
+        (gnus-tmp-marked-mark 
          (if (and (numberp number) 
                   (zerop number)
                   (cdr (assq 'tick gnus-tmp-marked)))
@@ -4352,7 +4445,7 @@ increase the score of each group you read."
        gnus-unread ,(if (numberp number)
                        (string-to-int gnus-tmp-number-of-unread)
                      t)
-       gnus-marked ,gnus-tmp-marked
+       gnus-marked ,gnus-tmp-marked-mark
        gnus-level ,gnus-tmp-level))
     ;; Allow XEmacs to remove front-sticky text properties.
     (gnus-group-remove-excess-properties)))
@@ -4421,7 +4514,7 @@ already."
       (when (> (length mode-string) max-len) 
        (setq mode-string (substring mode-string 0 (- max-len 4))))
       (prog1
-         (setq mode-line-buffer-identification mode-string)
+         (setq mode-line-buffer-identification (list mode-string))
        (set-buffer-modified-p t)))))
 
 (defun gnus-group-group-name ()
@@ -4633,6 +4726,12 @@ This means that no highlighting or scoring will be performed."
        gnus-summary-expunge-below)
     (gnus-group-read-group all t)))
 
+(defun gnus-group-visible-select-group (&optional all)
+  "Select the current group without hiding any articles."
+  (interactive "P")
+  (let ((gnus-inhibit-limiting t))
+    (gnus-group-read-group all t)))
+
 ;;;###autoload
 (defun gnus-fetch-group (group)
   "Start Gnus if necessary and enter GROUP.
@@ -4667,7 +4766,6 @@ Returns whether the fetching was successful or not."
        (gnus-group-read-group t t group)
       (error nil)
       (quit nil))
-;    (debug (current-buffer))
     (not (equal (current-buffer) cur))))
   
 (defun gnus-group-jump-to-group (group)
@@ -5011,17 +5109,21 @@ of the Earth\".  There is no undo."
 (defun gnus-group-make-help-group ()
   "Create the Gnus documentation group."
   (interactive)
-  (let ((path (cons (concat installation-directory "etc/") load-path))
+  (let ((path load-path)
        (name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help")))
-       file)
+       file dir)
     (and (gnus-gethash name gnus-newsrc-hashtb)
         (error "Documentation group already exists"))
-    (while (and path
-               (not (file-exists-p 
-                     (setq file (concat (file-name-as-directory (car path))
-                                        "gnus-tut.txt")))))
-      (setq path (cdr path)))
-    (if (not path)
+    (while path
+      (setq dir (file-name-as-directory (expand-file-name (pop path)))
+           file nil)
+      (when (or (file-exists-p (setq file (concat dir "gnus-tut.txt")))
+               (file-exists-p
+                (setq file (concat (file-name-directory 
+                                    (directory-file-name dir))
+                                   "etc/gnus-tut.txt"))))
+       (setq path nil)))
+    (if (not file)
        (message "Couldn't find doc group")
       (gnus-group-make-group 
        (gnus-group-real-name name)
@@ -5503,16 +5605,16 @@ The killed newsgroups can be yanked by using \\[gnus-group-yank-group]."
 The killed newsgroups can be yanked by using \\[gnus-group-yank-group].
 However, only groups that were alive can be yanked; already killed 
 groups or zombie groups can't be yanked.
-The return value is the name of the (last) group that was killed."
+The return value is the name of the group that was killed, or a list
+of groups killed."
   (interactive "P")
   (let ((buffer-read-only nil)
        (groups (gnus-group-process-prefix n))
-       group entry level)
-    (if (or t (< (length groups) 10))
+       group entry level out)
+    (if (< (length groups) 10)
        ;; This is faster when there are few groups.
        (while groups
-         (setq group (car groups)
-               groups (cdr groups))
+         (push (setq group (pop groups)) out)
          (gnus-group-remove-mark group)
          (setq level (gnus-group-group-level))
          (gnus-delete-line)
@@ -5525,24 +5627,33 @@ The return value is the name of the (last) group that was killed."
           (if entry entry group) gnus-level-killed (if entry nil level)))
       ;; If there are lots and lots of groups to be killed, we use
       ;; this thing instead.
-      ;; !!! Not written.
-      )
-      
+      (let (entry)
+       (setq groups (nreverse groups))
+       (while groups
+         (gnus-group-remove-mark (car groups))
+         (gnus-delete-line)
+         (setq entry (gnus-gethash (pop groups) gnus-newsrc-hashtb))
+         (push (cons (car entry) (nth 2 entry))
+               gnus-list-of-killed-groups)
+         (setcdr (cdr entry) (cdr (cdr (cdr entry)))))
+       (gnus-make-hashtable-from-newsrc-alist)))
+    
     (gnus-group-position-point)
-    group))
+    (if (< (length out) 2) (car out) (nreverse out))))
 
 (defun gnus-group-yank-group (&optional arg)
   "Yank the last newsgroups killed with \\[gnus-group-kill-group],
 inserting it before the current newsgroup.  The numeric ARG specifies
-how many newsgroups are to be yanked.  The name of the (last)
-newsgroup yanked is returned."
+how many newsgroups are to be yanked.  The name of the newsgroup yanked
+is returned, or (if several groups are yanked) a list of yanked groups
+is returned."
   (interactive "p")
-  (if (not arg) (setq arg 1))
-  (let (info group prev)
-    (while (>= (setq arg (1- arg)) 0)
-      (if (not (setq info (car gnus-list-of-killed-groups)))
+  (setq arg (or arg 1))
+  (let (info group prev out)
+    (while (>= (decf arg) 0)
+      (if (not (setq info (pop gnus-list-of-killed-groups)))
          (error "No more newsgroups to yank"))
-      (setq group (nth 1 info))
+      (push (setq group (nth 1 info)) out)
       ;; Find which newsgroup to insert this one before - search
       ;; backward until something suitable is found.  If there are no
       ;; other newsgroups in this buffer, just make this newsgroup the
@@ -5552,12 +5663,37 @@ newsgroup yanked is returned."
        info (nth 2 info) gnus-level-killed 
        (and prev (gnus-gethash prev gnus-newsrc-hashtb))
        t)
-      (gnus-group-insert-group-line-info group)
-      (setq gnus-list-of-killed-groups 
-           (cdr gnus-list-of-killed-groups)))
+      (gnus-group-insert-group-line-info group))
     (forward-line -1)
     (gnus-group-position-point)
-    group))
+    (if (< (length out) 2) (car out) (nreverse out))))
+
+(defun gnus-group-kill-level (level)
+  "Kill all groups that is on a certain LEVEL."
+  (interactive "nKill all groups on level: ")
+  (cond 
+   ((= level gnus-level-zombie)
+    (setq gnus-killed-list
+         (nconc gnus-zombie-list gnus-killed-list))
+    (setq gnus-zombie-list nil))
+   ((and (< level gnus-level-zombie)
+        (> level 0)
+        (or gnus-expert-user
+            (gnus-yes-or-no-p
+             (format 
+              "Do you really want to kill all groups on level %d? "
+              level))))
+    (let* ((prev gnus-newsrc-alist)
+          (alist (cdr prev)))
+      (while alist
+       (if (= (gnus-info-level level) level)
+           (setcdr prev (cdr alist))
+         (setq prev alist))
+       (setq alist (cdr alist)))
+      (gnus-make-hashtable-from-newsrc-alist)
+      (gnus-group-list-groups)))
+   (t
+    (error "Can't kill; illegal level: %d" level))))
       
 (defun gnus-group-list-all-groups (&optional arg)
   "List all newsgroups with level ARG or lower.
@@ -5641,6 +5777,13 @@ entail asking the server for the groups."
       (setq groups (cdr groups)))
     (goto-char (point-min))))
 
+(defun gnus-activate-all-groups (level)
+  "Activate absolutely all groups."
+  (interactive (list 7))
+  (let ((gnus-activate-level level)
+       (gnus-activate-foreign-newsgroups level))
+    (gnus-group-get-new-news)))
+
 (defun gnus-group-get-new-news (&optional arg)
   "Get newly arrived articles.
 If ARG is a number, it specifies which levels you are interested in
@@ -5662,9 +5805,9 @@ re-scanning.  If ARG is non-nil and not a number, this will force
   (if (and gnus-read-active-file (not arg))
       (progn
        (gnus-read-active-file)
-       (gnus-get-unread-articles (or arg (1+ gnus-level-subscribed))))
+       (gnus-get-unread-articles arg))
     (let ((gnus-read-active-file (if arg nil gnus-read-active-file)))
-      (gnus-get-unread-articles (or arg (1+ gnus-level-subscribed)))))
+      (gnus-get-unread-articles arg)))
   (gnus-group-list-groups))
 
 (defun gnus-group-get-new-news-this-group (&optional n)
@@ -5904,7 +6047,8 @@ The hook gnus-suspend-gnus-hook is called before actually suspending."
 (defun gnus-group-clear-dribble ()
   "Clear all information from the dribble buffer."
   (interactive)
-  (gnus-dribble-clear))
+  (gnus-dribble-clear)
+  (gnus-message 7 "Cleared dribble buffer"))
 
 (defun gnus-group-exit ()
   "Quit reading news after updating .newsrc.eld and .newsrc.
@@ -6079,8 +6223,9 @@ and the second element is the address."
        (erase-buffer))
       (gnus-browse-mode)
       (setq mode-line-buffer-identification
-           (format
-            "Gnus  Browse Server {%s:%s}" (car method) (car (cdr method))))
+           (list
+            (format
+             "Gnus: %%b {%s:%s}" (car method) (car (cdr method)))))
       (save-excursion
        (set-buffer nntp-server-buffer)
        (let ((cur (current-buffer)))
@@ -6357,6 +6502,8 @@ buffer.
   (define-key gnus-summary-mode-map "v" 'gnus-summary-verbose-headers)
   (define-key gnus-summary-mode-map "\C-c\C-b" 'gnus-bug)
 
+  (define-key gnus-summary-mode-map "*" 'gnus-cache-enter-article)
+  (define-key gnus-summary-mode-map "\M-*" 'gnus-cache-remove-article)
 
   ;; Sort of orthogonal keymap
   (define-prefix-command 'gnus-summary-mark-map)
@@ -6404,6 +6551,7 @@ buffer.
   (define-key gnus-summary-limit-map "v" 'gnus-summary-limit-to-score)
   (define-key gnus-summary-limit-map "D" 'gnus-summary-limit-include-dormant)
   (define-key gnus-summary-limit-map "d" 'gnus-summary-limit-exclude-dormant)
+;  (define-key gnus-summary-limit-map "t" 'gnus-summary-limit-exclude-thread)
   (define-key gnus-summary-mark-map "E" 'gnus-summary-limit-include-expunged)
   (define-key gnus-summary-limit-map "c" 
     'gnus-summary-limit-exclude-childless-dormant)
@@ -6788,9 +6936,7 @@ article number."
   '(progn
      (gnus-summary-skip-intangible)
      (or (get-text-property (point) 'gnus-number) 
-        (progn
-          (forward-line -1)
-          gnus-newsgroup-end))))
+        (gnus-summary-last-subject))))
 
 (defmacro gnus-summary-article-header (&optional number)
   `(gnus-data-header (gnus-data-find
@@ -6936,7 +7082,11 @@ article number."
            (if (< gnus-tmp-score gnus-summary-default-score)
                gnus-score-below-mark gnus-score-over-mark)))
         (gnus-tmp-replied (cond (gnus-tmp-process gnus-process-mark)
+                                ((memq gnus-tmp-current gnus-newsgroup-cached)
+                                 gnus-cached-mark)
                                 (gnus-tmp-replied gnus-replied-mark)
+                                ((memq gnus-tmp-current gnus-newsgroup-saved)
+                                 gnus-saved-mark)
                                 (t gnus-unread-mark)))
         (gnus-tmp-from (mail-header-from gnus-tmp-header))
         (gnus-tmp-name 
@@ -7044,7 +7194,7 @@ If NO-DISPLAY, don't generate a summary buffer."
      ;; This summary buffer exists already, so we just select it. 
      ((not new-group)
       (gnus-set-global-variables)
-      (gnus-kill-buffer kill-buffer)
+      (gnus-kill-or-deaden-summary kill-buffer)
       (gnus-configure-windows 'summary 'force)
       (gnus-set-mode-line 'summary)
       (gnus-summary-position-point)
@@ -7074,7 +7224,7 @@ If NO-DISPLAY, don't generate a summary buffer."
       (and (eq major-mode 'gnus-summary-mode)
           (not (equal (current-buffer) kill-buffer))
           (kill-buffer (current-buffer)))
-      (gnus-kill-buffer kill-buffer)
+      (gnus-kill-or-deaden-summary kill-buffer)
       (if (not quit-config)
          (progn
            (set-buffer gnus-group-buffer)
@@ -7124,7 +7274,7 @@ If NO-DISPLAY, don't generate a summary buffer."
            ;; This newsgroup is empty.
            (gnus-summary-catchup-and-exit nil t) ;Without confirmations.
            (gnus-message 6 "No unread news")
-           (gnus-kill-buffer kill-buffer)
+           (gnus-kill-or-deaden-summary kill-buffer)
            ;; Return nil from this function.
            nil)
        ;; Hide conversation thread subtrees.  We cannot do this in
@@ -7150,7 +7300,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        ;; If we are in async mode, we send some info to the backend.
        (when gnus-newsgroup-async
          (gnus-request-asynchronous gnus-newsgroup-name gnus-newsgroup-data))
-       (gnus-kill-buffer kill-buffer)
+       (gnus-kill-or-deaden-summary kill-buffer)
        (when (get-buffer-window gnus-group-buffer)
          ;; Gotta use windows, because recenter does wierd stuff if
          ;; the current buffer ain't the displayed window.
@@ -7420,47 +7570,70 @@ If NO-DISPLAY, don't generate a summary buffer."
   (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207" ; 
        (vector thread) 2))
 
+(defsubst gnus-article-sort-by-number (h1 h2)
+  "Sort articles by article number."
+  (< (mail-header-number h1)
+     (mail-header-number h2)))
+
 (defun gnus-thread-sort-by-number (h1 h2)
   "Sort threads by root article number."
-  (< (mail-header-number (gnus-thread-header h1))
-     (mail-header-number (gnus-thread-header h2))))
+  (gnus-article-sort-by-number 
+   (gnus-thread-header h1) (gnus-thread-header h2)))
 
-(defun gnus-thread-sort-by-author (h1 h2)
-  "Sort threads by root author."
+(defsubst gnus-article-sort-by-author (h1 h2)
+  "Sort articles by root author."
   (string-lessp
    (let ((extract (funcall 
                   gnus-extract-address-components
-                  (mail-header-from (gnus-thread-header h1)))))
+                  (mail-header-from h1))))
      (or (car extract) (cdr extract)))
    (let ((extract (funcall
                   gnus-extract-address-components 
-                  (mail-header-from (gnus-thread-header h2)))))
+                  (mail-header-from h2))))
      (or (car extract) (cdr extract)))))
 
+(defun gnus-thread-sort-by-author (h1 h2)
+  "Sort threads by root author."
+  (gnus-article-sort-by-author
+   (gnus-thread-header h1)  (gnus-thread-header h2)))
+
+(defsubst gnus-article-sort-by-subject (h1 h2)
+  "Sort articles by root subject."
+  (string-lessp
+   (downcase (gnus-simplify-subject-re (mail-header-subject h1)))
+   (downcase (gnus-simplify-subject-re (mail-header-subject h2)))))
+
 (defun gnus-thread-sort-by-subject (h1 h2)
   "Sort threads by root subject."
+  (gnus-article-sort-by-subject 
+   (gnus-thread-header h1) (gnus-thread-header h2)))
+
+(defsubst gnus-article-sort-by-date (h1 h2)
+  "Sort articles by root article date."
   (string-lessp
-   (downcase (gnus-simplify-subject-re
-             (mail-header-subject (gnus-thread-header h1))))
-   (downcase (gnus-simplify-subject-re 
-             (mail-header-subject (gnus-thread-header h2))))))
+   (gnus-sortable-date (mail-header-date h1))
+   (gnus-sortable-date (mail-header-date h2))))
 
 (defun gnus-thread-sort-by-date (h1 h2)
   "Sort threads by root article date."
-  (string-lessp
-   (gnus-sortable-date (mail-header-date (gnus-thread-header h1)))
-   (gnus-sortable-date (mail-header-date (gnus-thread-header h2)))))
+  (gnus-article-sort-by-date 
+   (gnus-thread-header h1) (gnus-thread-header h2)))
 
-(defun gnus-thread-sort-by-score (h1 h2)
-  "Sort threads by root article score.
+(defsubst gnus-article-sort-by-score (h1 h2)
+  "Sort articles by root article score.
 Unscored articles will be counted as having a score of zero."
-  (> (or (cdr (assq (mail-header-number (gnus-thread-header h1))
+  (> (or (cdr (assq (mail-header-number h1)
                    gnus-newsgroup-scored))
         gnus-summary-default-score 0)
-     (or (cdr (assq (mail-header-number (gnus-thread-header h2))
+     (or (cdr (assq (mail-header-number h2)
                    gnus-newsgroup-scored))
         gnus-summary-default-score 0)))
 
+(defun gnus-thread-sort-by-score (h1 h2)
+  "Sort threads by root article score."
+  (gnus-article-sort-by-score 
+   (gnus-thread-header h1) (gnus-thread-header h2)))
+
 (defun gnus-thread-sort-by-total-score (h1 h2)
   "Sort threads by the sum of all scores in the thread.
 Unscored articles will be counted as having a score of zero."
@@ -7696,6 +7869,8 @@ or a straight list of headers."
             gnus-tmp-replied
             (cond ((memq number gnus-newsgroup-processable)
                    gnus-process-mark)
+                  ((memq number gnus-newsgroup-cached)
+                   gnus-cached-mark)
                   ((memq number gnus-newsgroup-replied)
                    gnus-replied-mark)
                   (t gnus-unread-mark))
@@ -7948,7 +8123,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
         (types '((marked . tick) (replied . reply) 
                  (expirable . expire) (killed . killed)
                  (bookmarks . bookmark) (dormant . dormant)
-                 (scored . score)))
+                 (scored . score) (saved . save)))
         (uncompressed '(score bookmark))
         marks var articles article mark)
 
@@ -7965,7 +8140,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
       ;; All articles have to be subsets of the active articles.  
       (cond 
        ;; Adjust "simple" lists.
-       ((memq mark '(tick dormant expirable reply killed))
+       ((memq mark '(tick dormant expirable reply killed save))
        (while articles
          (when (or (< (setq article (pop articles)) min) (> article max))
            (set var (delq article (symbol-value var))))))
@@ -7981,7 +8156,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
   (let ((types '((marked . tick) (replied . reply) 
                 (expirable . expire) (killed . killed)
                 (bookmarks . bookmark) (dormant . dormant)
-                (scored . score)))
+                (scored . score) (saved . save)))
        (info (gnus-get-info gnus-newsgroup-name))
        (uncompressed '(score bookmark killed))
        var type list newmarked symbol)
@@ -8081,7 +8256,7 @@ If WHERE is `summary', the summary mode line format will be used."
          ;; Pad the mode string a bit.
          (setq mode-string (format (format "%%-%ds" max-len) mode-string))))
       ;; Update the mode line.
-      (setq mode-line-buffer-identification mode-string)
+      (setq mode-line-buffer-identification (list mode-string))
       (set-buffer-modified-p t))))
 
 (defun gnus-create-xref-hashtb (from-newsgroup headers unreads)
@@ -8610,15 +8785,15 @@ If EXCLUDE-GROUP, do not go to this group."
                (not (gnus-data-unread-p (car arts))))
        (setq arts (cdr arts)))
       (when (setq result
-               (if unread
-                   (progn
-                     (while arts
-                       (when (gnus-data-unread-p (car arts))
-                         (setq result (car arts)
-                               arts nil))
-                       (setq arts (cdr arts)))
-                     result)
-                 (car arts)))
+                 (if unread
+                     (progn
+                       (while arts
+                         (when (gnus-data-unread-p (car arts))
+                           (setq result (car arts)
+                                 arts nil))
+                         (setq arts (cdr arts)))
+                       result)
+                   (car arts)))
        (goto-char (gnus-data-pos result))
        (gnus-data-number result)))))
 
@@ -8823,7 +8998,7 @@ The prefix argument ALL means to select all articles."
   (let ((current-subject (gnus-summary-article-number))
        (group gnus-newsgroup-name))
     (setq gnus-newsgroup-begin nil)
-    (gnus-summary-exit t)
+    (gnus-summary-exit)
     ;; We have to adjust the point of group mode buffer because the
     ;; current point was moved to the next unread newsgroup by
     ;; exiting.
@@ -8896,7 +9071,9 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
     ;; Make all changes in this group permanent.
     (gnus-summary-update-info)         
     (set-buffer buf)
-    (and gnus-use-cache (gnus-cache-possibly-remove-articles))
+    (when gnus-use-cache
+      (gnus-cache-possibly-remove-articles)
+      (gnus-cache-save-buffers))
     ;; Make sure where I was, and go to next newsgroup.
     (set-buffer gnus-group-buffer)
     (or quit-config
@@ -8905,21 +9082,21 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
          (gnus-group-next-unread-group 1)))
     (if temporary
        nil                             ;Nothing to do.
-      ;; 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.
-      (gnus-configure-windows 'group 'force)
-      (gnus-summary-clear-local-variables)
-      ;; Return to group mode buffer. 
-      (if (eq mode 'gnus-summary-mode)
-         (gnus-kill-buffer buf))
-      (if (get-buffer gnus-article-buffer)
-         (bury-buffer gnus-article-buffer))
+      (if (not gnus-kill-summary-on-exit)
+         (gnus-deaden-summary)
+       ;; 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.
+       (gnus-configure-windows 'group 'force)
+       (gnus-summary-clear-local-variables)
+       ;; Return to group mode buffer. 
+       (if (eq mode 'gnus-summary-mode)
+           (gnus-kill-buffer buf)))
       (setq gnus-current-select-method gnus-select-method)
       (pop-to-buffer gnus-group-buffer)
       ;; Clear the current group name.
@@ -8946,18 +9123,18 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
     (when (or no-questions
              gnus-expert-user
              (gnus-y-or-n-p "Do you really wanna quit reading this group? "))
-      (gnus-close-group group)
-      (gnus-summary-clear-local-variables)
-      (set-buffer gnus-group-buffer)
-      (gnus-summary-clear-local-variables)
+      (if (not gnus-kill-summary-on-exit)
+         (gnus-deaden-summary)
+       (gnus-close-group group)
+       (gnus-summary-clear-local-variables)
+       (set-buffer gnus-group-buffer)
+       (gnus-summary-clear-local-variables)
+       (when (get-buffer gnus-summary-buffer)
+         (kill-buffer gnus-summary-buffer)))
       ;; Return to the group buffer.
       (gnus-configure-windows 'group 'force)
       ;; Clear the current group name.
       (setq gnus-newsgroup-name nil)
-      (when (get-buffer gnus-summary-buffer)
-       (kill-buffer gnus-summary-buffer))
-      (when (get-buffer gnus-article-buffer)
-       (bury-buffer gnus-article-buffer))
       (when (equal (gnus-group-group-name) group)
        (gnus-group-next-unread-group 1))
       (when quit-config
@@ -8968,6 +9145,78 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
            (gnus-set-global-variables))
          (gnus-configure-windows (cdr quit-config)))))))
 
+;;; Dead summaries.
+
+(defvar gnus-dead-summary-mode-map nil)
+
+(if gnus-dead-summary-mode-map
+    nil
+  (setq gnus-dead-summary-map (make-keymap))
+  (suppress-keymap gnus-dead-summary-map)
+  (substitute-key-definition
+   'undefined 'gnus-summary-wake-up-the-dead gnus-dead-summary-map)
+  (let ((keys '("\C-d" "\r" "\177")))
+    (while keys
+      (define-key gnus-dead-summary-map
+       (pop keys) 'gnus-summary-wake-up-the-dead))))
+(defvar gnus-dead-summary-mode nil
+  "Minor mode for Gnus summary buffers.")
+
+(defun gnus-dead-summary-mode (&optional arg)
+  "Minor mode for Gnus summary buffers."
+  (interactive "P")
+  (when (eq major-mode 'gnus-summary-mode)
+    (make-local-variable 'gnus-dead-summary-mode)
+    (setq gnus-dead-summary-mode 
+         (if (null arg) (not gnus-dead-summary-mode)
+           (> (prefix-numeric-value arg) 0)))
+    (when gnus-dead-summary-mode
+      (unless (assq 'gnus-dead-summary-mode minor-mode-alist)
+       (push '(gnus-dead-summary-mode " Dead") minor-mode-alist))
+      (unless (assq 'gnus-dead-summary-mode minor-mode-map-alist)
+       (push (cons 'gnus-dead-summary-mode gnus-dead-summary-mode-map)
+             minor-mode-map-alist)))))
+
+(defun gnus-deaden-summary ()
+  "Make the current summary buffer into a dead summary buffer."
+  ;; Kill any previous dead summary buffer.
+  (when (and gnus-dead-summary
+            (buffer-name gnus-dead-summary))
+    (save-excursion
+      (set-buffer gnus-dead-summary)
+      (when gnus-dead-summary-mode
+       (kill-buffer (current-buffer)))))
+  ;; Make this the current dead summary.
+  (setq gnus-dead-summary (current-buffer))
+  (gnus-dead-summary-mode 1)
+  (let ((name (buffer-name)))
+    (when (string-match "Summary" name)
+      (rename-buffer
+       (concat (substring name 0 (match-beginning 0)) "Dead "
+              (substring name (match-beginning 0))) t))))
+
+(defun gnus-kill-or-deaden-summary (buffer)
+  "Kill or deaden the summary BUFFER."
+  (cond (gnus-kill-summary-on-exit
+        (gnus-kill-buffer buffer))
+       ((and (get-buffer buffer)
+             (buffer-name (get-buffer buffer)))
+        (save-excursion
+          (set-buffer buffer)
+          (gnus-deaden-summary)))))
+
+(defun gnus-summary-wake-up-the-dead (&rest args)
+  "Wake up the dead summary buffer."
+  (interactive)
+  (gnus-dead-summary-mode -1)
+  (let ((name (buffer-name)))
+    (when (string-match "Dead " name)
+      (rename-buffer
+       (concat (substring name 0 (match-beginning 0))
+              (substring name (match-end 0))) t)))
+  (gnus-message 3 "This dead summary is now alive again"))
+
 ;; Suggested by Andrew Eskilsson <pi92ae@pt.hk-r.se>.
 (defun gnus-summary-fetch-faq (&optional faq-dir)
   "Fetch the FAQ for the current group.
@@ -9239,8 +9488,6 @@ If BACKWARD, the previous article is selected instead of the next."
        ;; For some reason, the group window gets selected.  We change
        ;; it back.  
        (select-window (get-buffer-window (current-buffer)))
-       ;; 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)
@@ -9257,41 +9504,52 @@ If BACKWARD, the previous article is selected instead of the next."
                            "exiting"))
            (gnus-summary-next-group nil group backward)))
         (t
-         (let ((keystrokes '(?\C-n ?\C-p))
-               key)
-           (while (or (null key) (memq key keystrokes))
-             (gnus-message 
-              7 "No more%s articles%s" (if unread " unread" "")
-              (if (and group 
-                       (not (gnus-ephemeral-group-p gnus-newsgroup-name)))
-                  (format " (Type %s for %s [%s])"
-                          (single-key-description cmd) group
-                          (car (gnus-gethash group gnus-newsrc-hashtb)))
-                (format " (Type %s to exit %s)"
-                        (single-key-description cmd)
-                        gnus-newsgroup-name)))
-             ;; Confirm auto selection.
-             (let* ((event (read-char-exclusive)))
-               (setq key (if (listp event) (car event) event))
-               (if (memq key keystrokes)
-                   (let ((obuf (current-buffer)))
-                     (switch-to-buffer gnus-group-buffer)
-                     (and group
-                          (gnus-group-jump-to-group group))
-                     (condition-case ()
-                         (cond ((= key ?\C-n)
-                                (gnus-group-next-unread-group 1))
-                               ((= key ?\C-p)
-                                (gnus-group-prev-unread-group 1)))
-                       (error (ding) nil))
-                     (setq group (gnus-group-group-name))
-                     (switch-to-buffer obuf)))))
-           (if (equal key cmd)
-               (if (or (not group)
-                       (gnus-ephemeral-group-p gnus-newsgroup-name))
-                   (gnus-summary-exit)
-                 (gnus-summary-next-group nil group backward))
-             (execute-kbd-macro (char-to-string key)))))))))))
+         (gnus-summary-walk-group-buffer 
+          gnus-newsgroup-name cmd unread backward))))))))
+
+(defun gnus-summary-walk-group-buffer (from-group cmd unread backward)
+  (let ((keystrokes '((?\C-n (gnus-group-next-unread-group 1))
+                     (?\C-p (gnus-group-prev-unread-group 1))))
+       keve key group ended)
+    (while (not ended)
+      (save-excursion
+       (set-buffer gnus-group-buffer)
+       (setq group (gnus-group-group-name)))
+      (gnus-message 
+       7 "No more%s articles%s" (if unread " unread" "")
+       (if (and group 
+               (not (gnus-ephemeral-group-p gnus-newsgroup-name)))
+          (format " (Type %s for %s [%s])"
+                  (single-key-description cmd) group
+                  (car (gnus-gethash group gnus-newsrc-hashtb)))
+        (format " (Type %s to exit %s)"
+                (single-key-description cmd)
+                gnus-newsgroup-name)))
+      ;; Confirm auto selection.
+      (setq key (car (setq keve (gnus-read-event-char))))
+      (setq ended t)
+      (cond 
+       ((assq key keystrokes)
+       (let ((obuf (current-buffer)))
+         (switch-to-buffer gnus-group-buffer)
+         (and group
+              (gnus-group-jump-to-group group))
+         (eval (car (cdr (assq key keystrokes))))
+         (setq group (gnus-group-group-name))
+         (switch-to-buffer obuf))
+       (setq ended nil))
+       ((equal key cmd)
+       (if (or (not group)
+               (gnus-ephemeral-group-p gnus-newsgroup-name))
+           (gnus-summary-exit)
+         (gnus-summary-next-group nil group backward)))
+       (t
+       (push (cdr keve) unread-command-events))))))
+
+(defun gnus-read-event-char ()
+  "Get the next event."
+  (let ((event (read-event)))
+    (cons (and (numberp event) event) event)))
 
 (defun gnus-summary-next-unread-article ()
   "Select unread article after current one."
@@ -9435,6 +9693,12 @@ Return nil if there are no unread articles."
       (error "No unread articles"))
     (gnus-summary-position-point)))
 
+(defun gnus-summary-last-subject ()
+  "Go to the last displayed subject line in the group."
+  (let ((article (gnus-data-number (car (gnus-data-list t)))))
+    (when article
+      (gnus-summary-goto-subject article))))
+
 (defun gnus-summary-goto-article (article &optional all-headers force)
   "Fetch ARTICLE and display it if it exists.
 If ALL-HEADERS is non-nil, no header lines are hidden."
@@ -9645,20 +9909,25 @@ Returns how many articles were removed."
 This entails weeding out unwanted dormants, low-scored articles,
 fetch-old-headers verbiage, and so on."
   ;; Most groups have nothing to remove.
-  (if (and (null gnus-newsgroup-dormant)
-          (not (eq gnus-fetch-old-headers 'some))
-          (null gnus-summary-expunge-below))
+  (if (or gnus-inhibit-limiting
+         (and (null gnus-newsgroup-dormant)
+              (not (eq gnus-fetch-old-headers 'some))
+              (null gnus-summary-expunge-below)
+              (null gnus-thread-expunge-below)))
       () ; Do nothing.
-    (setq gnus-newsgroup-limits 
-         (cons gnus-newsgroup-limit gnus-newsgroup-limits))
+    (push gnus-newsgroup-limit gnus-newsgroup-limits)
     (setq gnus-newsgroup-limit nil)
     (mapatoms
      (lambda (node)
-       (if (null (car (symbol-value node)))
-          (let ((nodes (cdr (symbol-value node))))
-            (while nodes
-              (gnus-summary-limit-children (car nodes))
-              (setq nodes (cdr nodes))))))
+       (unless (car (symbol-value node))
+        ;; These threads have no parents -- they are roots.
+        (let ((nodes (cdr (symbol-value node))))
+          (while nodes
+            (if (and gnus-thread-expunge-below
+                     (< (gnus-thread-total-score (car nodes))
+                        gnus-thread-expunge-below))
+                (gnus-expunge-thread (pop nodes))
+              (gnus-summary-limit-children (pop nodes)))))))
      gnus-newsgroup-dependencies)
     (when (not gnus-newsgroup-limit)
       (setq gnus-newsgroup-limit (pop gnus-newsgroup-limits)))
@@ -9672,8 +9941,7 @@ fetch-old-headers verbiage, and so on."
   ;; working its way up towards the root.
   (let ((children 
         (if (cdr thread)
-            (apply '+ (mapcar (lambda (th)
-                                (gnus-summary-limit-children th))
+            (apply '+ (mapcar 'gnus-summary-limit-children 
                               (cdr thread)))
           0))
        (number (mail-header-number (car thread)))
@@ -9715,6 +9983,20 @@ fetch-old-headers verbiage, and so on."
       (setq gnus-newsgroup-limit (cons number gnus-newsgroup-limit))
       1)))
 
+(defun gnus-expunge-thread (thread)
+  "Mark all articles in THREAD as read."
+  (let* ((number (mail-header-number (car thread))))
+    (incf gnus-newsgroup-expunged-tally)
+    ;; We also mark as read here, if that's wanted.
+    (setq gnus-newsgroup-unreads 
+         (delq number gnus-newsgroup-unreads))
+    (if gnus-newsgroup-auto-expire
+       (push number gnus-newsgroup-expirable)
+      (push (cons number gnus-low-score-mark)
+           gnus-newsgroup-reads)))
+  ;; Go recursively through all subthreads.
+  (mapcar 'gnus-expunge-thread (cdr thread)))
+
 ;; Summary article oriented commands
 
 (defun gnus-summary-refer-parent-article (n)
@@ -10051,11 +10333,8 @@ If ARG is a negative number, hide the unwanted header lines."
        (goto-char (point-min))
        (setq e (1- (or (search-forward "\n\n" nil t) (point-max)))))
       (insert-buffer-substring gnus-original-article-buffer 1 e)
-      (let ((hook (delq 'gnus-article-hide-headers-if-wanted
-                       (delq 'gnus-article-hide-headers
-                             (copy-sequence gnus-article-display-hook))))
-           (gnus-inhibit-hiding t))
-       (run-hooks 'hook))
+      (let ((gnus-inhibit-hiding t))
+       (run-hooks 'gnus-article-display-hook))
       (if (or (not hidden) (and (numberp arg) (< arg 0)))
          (gnus-article-hide-headers)))))
 
@@ -10184,6 +10463,7 @@ and `request-accept' functions. (Ie. mail newsgroups at present.)"
                             (dormant . gnus-newsgroup-dormant)
                             (expire . gnus-newsgroup-expirable)
                             (bookmark . gnus-newsgroup-bookmarks)
+                            (save . gnus-newsgroup-saved)
                             (reply . gnus-newsgroup-replied)))
                    (to-article (cdr art-group)))
 
@@ -10323,6 +10603,7 @@ functions. (Ie. mail newsgroups at present.)"
                             (dormant . gnus-newsgroup-dormant)
                             (expire . gnus-newsgroup-expirable)
                             (bookmark . gnus-newsgroup-bookmarks)
+                            (save . gnus-newsgroup-saved)
                             (reply . gnus-newsgroup-replied)))
                    (to-article (cdr art-group)))
 
@@ -10698,10 +10979,8 @@ the actual number of articles marked is returned."
   "Mark ARTICLE replied and update the summary line."
   (setq gnus-newsgroup-replied (cons article gnus-newsgroup-replied))
   (let ((buffer-read-only nil))
-    (if (gnus-summary-goto-subject article)
-       (progn
-         (gnus-summary-update-mark gnus-replied-mark 'replied)
-         t))))
+    (when (gnus-summary-goto-subject article)
+      (gnus-summary-update-secondary-mark article))))
 
 (defun gnus-summary-set-bookmark (article)
   "Set a bookmark in current article."
@@ -10760,24 +11039,22 @@ the actual number of articles marked is returned."
   (setq gnus-newsgroup-processable 
        (cons article 
              (delq article gnus-newsgroup-processable)))
-  (let ((buffer-read-only nil))
-    (if (gnus-summary-goto-subject article)
-       (progn
-         (gnus-summary-show-thread)
-         (gnus-summary-update-mark gnus-process-mark 'replied)
-         t))))
+  (when (gnus-summary-goto-subject article)
+    (gnus-summary-show-thread)
+    (gnus-summary-update-secondary-mark article)))
 
 (defun gnus-summary-remove-process-mark (article)
   "Remove the process mark from ARTICLE and update the summary line."
   (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable))
-  (let ((buffer-read-only nil))
-    (if (gnus-summary-goto-subject article)
-       (progn
-         (gnus-summary-show-thread)
-         (gnus-summary-update-mark ?  'replied)
-         (if (memq article gnus-newsgroup-replied) 
-             (gnus-summary-update-mark gnus-replied-mark 'replied))
-         t))))
+  (when (gnus-summary-goto-subject article)
+    (gnus-summary-show-thread)
+    (gnus-summary-update-secondary-mark article)))
+
+(defun gnus-summary-set-saved-mark (article)
+  "Set the process mark on ARTICLE and update the summary line."
+  (push article gnus-newsgroup-saved)
+  (when (gnus-summary-goto-subject article)
+    (gnus-summary-update-secondary-mark article)))
 
 (defun gnus-summary-mark-forward (n &optional mark no-expire)
   "Mark N articles as read forwards.
@@ -10905,6 +11182,23 @@ marked."
          (gnus-summary-update-mark mark 'unread)
          t))))
 
+(defun gnus-summary-update-secondary-mark (article)
+  "Update the secondary (read, process, cache) mark."
+  (gnus-summary-update-mark
+   (cond ((memq article gnus-newsgroup-processable)
+         gnus-process-mark)
+        ((memq article gnus-newsgroup-cached)
+         gnus-cached-mark)
+        ((memq article gnus-newsgroup-replied)
+         gnus-replied-mark)
+        ((memq article gnus-newsgroup-saved)
+         gnus-saved-mark)
+        (t gnus-unread-mark))
+   'replied)
+  (when (gnus-visual-p 'summary-highlight 'highlight)
+    (run-hooks 'gnus-summary-update-hook))
+  t)
+
 (defun gnus-summary-update-mark (mark type)
   (beginning-of-line)
   (let ((forward (cdr (assq type gnus-summary-mark-positions)))
@@ -11196,7 +11490,7 @@ read."
   (interactive "P")
   (gnus-set-global-variables)
   (gnus-summary-catchup all)
-  (gnus-summary-next-group))
+  (gnus-summary-next-article t))
 
 ;; Thread-based commands.
 
@@ -11431,100 +11725,52 @@ If the prefix argument is negative, tick articles instead."
   "Sort summary buffer by article number.
 Argument REVERSE means reverse order."
   (interactive "P")
-  (gnus-set-global-variables)
-  (gnus-summary-sort 
-   ;; `gnus-summary-article-number' is a macro, and `sort-subr' wants
-   ;; a function, so we wrap it.
-   (cons (lambda () (gnus-summary-article-number))
-        'gnus-thread-sort-by-number) reverse))
+  (gnus-summary-sort 'number reverse))
 
 (defun gnus-summary-sort-by-author (&optional reverse)
   "Sort summary buffer by author name alphabetically.
 If case-fold-search is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
   (interactive "P")
-  (gnus-set-global-variables)
-  (gnus-summary-sort
-   (cons
-    (lambda ()
-      (let* ((header (gnus-summary-article-header))
-            extract)
-       (if (not (vectorp header))
-           ""
-         (setq extract (funcall gnus-extract-address-components
-                        (mail-header-from header)))
-         (concat (or (car extract) (cdr extract))
-                 "\r" (mail-header-subject header)))))
-    'gnus-thread-sort-by-author)
-   reverse))
+  (gnus-summary-sort 'author reverse))
 
 (defun gnus-summary-sort-by-subject (&optional reverse)
   "Sort summary buffer by subject alphabetically. `Re:'s are ignored.
 If case-fold-search is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
   (interactive "P")
-  (gnus-set-global-variables)
-  (gnus-summary-sort
-   (cons
-    (lambda ()
-      (let* ((header (gnus-summary-article-header))
-            extract)
-       (if (not (vectorp header))
-           ""
-         (setq extract (funcall gnus-extract-address-components
-                                (mail-header-from header)))
-         (concat 
-          (downcase (gnus-simplify-subject (gnus-summary-article-subject) t))
-          "\r" (or (car extract) (cdr extract))))))
-    'gnus-thread-sort-by-subject)
-   reverse))
+  (gnus-summary-sort 'subject reverse))
 
 (defun gnus-summary-sort-by-date (&optional reverse)
   "Sort summary buffer by date.
 Argument REVERSE means reverse order."
   (interactive "P")
-  (gnus-set-global-variables)
-  (gnus-summary-sort
-   (cons
-    (lambda ()
-      (gnus-sortable-date
-       (mail-header-date 
-       (gnus-summary-article-header))))
-    'gnus-thread-sort-by-date)
-   reverse))
+  (gnus-summary-sort 'date reverse))
 
 (defun gnus-summary-sort-by-score (&optional reverse)
   "Sort summary buffer by score.
 Argument REVERSE means reverse order."
   (interactive "P")
-  (gnus-set-global-variables)
-  (gnus-summary-sort 
-   (cons (lambda () (gnus-summary-article-score))
-        'gnus-thread-sort-by-score)
-   (not reverse)))
+  (gnus-summary-sort 'score reverse))
 
 (defun gnus-summary-sort (predicate reverse)
-  "Sort summary buffer by PREDICATE.  REVERSE means reverse order. 
-PREDICATE is a cons of `(unthreaded-func . threaded-func)'."
-  (let (buffer-read-only)
-    (if (not gnus-show-threads)
-       ;; We do untreaded sorting...
-       (progn
-         (goto-char (point-min))
-         (sort-subr reverse 'forward-line 'end-of-line (car predicate))
-         (gnus-data-compute-positions))
-      ;; ... or we do threaded sorting.
-      (let ((gnus-thread-sort-functions (list (cdr predicate)))
-           (gnus-summary-prepare-hook nil))
-       ;; We do that by simply regenerating the threads.
-       (gnus-summary-prepare)
-       ;; Hide subthreads if needed.
-       (when gnus-thread-hide-subtree
-         (gnus-summary-hide-all-threads))))
-    ;; If in async mode, we send some info to the backend.
-    (when gnus-newsgroup-async
-      (gnus-request-asynchronous 
-       gnus-newsgroup-name gnus-newsgroup-data))))
+  "Sort summary buffer by PREDICATE.  REVERSE means reverse order."
+  (gnus-set-global-variables)
+  (let* ((gnus-thread-sort-functions 
+         (list (intern (format "gnus-thread-sort-by-%s" predicate))))
+        (gnus-article-sort-functions
+         (list (intern (format "gnus-article-sort-by-%s" predicate))))
+        (buffer-read-only)
+        (gnus-summary-prepare-hook nil))
+    ;; We do the sorting by regenerating the threads.
+    (gnus-summary-prepare)
+    ;; Hide subthreads if needed.
+    (when (and gnus-show-threads gnus-thread-hide-subtree)
+      (gnus-summary-hide-all-threads)))
+  ;; If in async mode, we send some info to the backend.
+  (when gnus-newsgroup-async
+    (gnus-request-asynchronous 
+     gnus-newsgroup-name gnus-newsgroup-data)))
   
 (defun gnus-sortable-date (date)
   "Make sortable string by string-lessp from DATE.
@@ -11541,7 +11787,7 @@ Timezone package is used."
 
 ;; Summary saving commands.
 
-(defun gnus-summary-save-article (&optional n)
+(defun gnus-summary-save-article (&optional n not-saved)
   "Save the current article using the default saver function.
 If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
@@ -11551,47 +11797,45 @@ The variable `gnus-default-article-saver' specifies the saver function."
   (interactive "P")
   (gnus-set-global-variables)
   (let ((articles (gnus-summary-work-articles n))
-       file)
+       file header article)
     (while articles
-      (let ((header (gnus-summary-article-header (car articles))))
-       (if (vectorp header)
-           (progn
-             (save-window-excursion
-               (gnus-summary-select-article t nil nil (car articles)))
-             (or gnus-save-all-headers
-                 ;; Remove headers accoring to `gnus-saved-headers'.
-                 (let ((gnus-visible-headers 
-                        (or gnus-saved-headers gnus-visible-headers)))
-                   (gnus-article-hide-headers t)))
-             ;; Remove any X-Gnus lines.
-             (save-excursion
-               (save-restriction
-                 (set-buffer gnus-article-buffer)
-                 (let ((buffer-read-only nil))
-                   (goto-char (point-min))
-                   (narrow-to-region (point) (or (search-forward "\n\n" nil t)
-                                                 (point-max)))
-                   (while (re-search-forward "^X-Gnus" nil t)
-                     (beginning-of-line)
-                     (delete-region (point)
-                                    (progn (forward-line 1) (point))))
-                   (widen))))
-             (save-window-excursion
-               (if gnus-default-article-saver
-                   (setq file (funcall
-                               gnus-default-article-saver
-                               (cond
-                                ((not gnus-prompt-before-saving)
-                                 'default)
-                                ((eq gnus-prompt-before-saving 'always)
-                                 nil)
-                                (t file))))
-                 (error "No default saver is defined."))))
+      (setq header (gnus-summary-article-header
+                   (setq article (pop articles))))
+      (if (not (vectorp header))
+         ;; This is a pseudo-article.
          (if (assq 'name header)
              (gnus-copy-file (cdr (assq 'name header)))
-           (gnus-message 1 "Article %d is unsaveable" (car articles)))))
-      (gnus-summary-remove-process-mark (car articles))
-      (setq articles (cdr articles)))
+           (gnus-message 1 "Article %d is unsaveable" article))
+       ;; This is a real article.
+       (save-window-excursion
+         (gnus-summary-select-article t nil nil article))
+       (unless gnus-save-all-headers
+         ;; Remove headers accoring to `gnus-saved-headers'.
+         (let ((gnus-visible-headers 
+                (or gnus-saved-headers gnus-visible-headers)))
+           (gnus-article-hide-headers t)))
+       ;; Remove any X-Gnus lines.
+       (save-excursion
+         (set-buffer gnus-article-buffer)
+         (save-restriction
+           (let ((buffer-read-only nil))
+             (gnus-narrow-to-headers)
+             (while (re-search-forward "^X-Gnus" nil t)
+               (gnus-delete-line)))))
+       (save-window-excursion
+         (if (not gnus-default-article-saver)
+             (error "No default saver is defined.")
+           (setq file (funcall
+                       gnus-default-article-saver
+                       (cond
+                        ((not gnus-prompt-before-saving)
+                         'default)
+                        ((eq gnus-prompt-before-saving 'always)
+                         nil)
+                        (t file))))))
+       (gnus-summary-remove-process-mark article)
+       (unless not-saved
+         (gnus-summary-set-saved-mark article))))
     (gnus-summary-position-point)
     n))
 
@@ -11604,7 +11848,7 @@ pipe those articles instead."
   (interactive "P")
   (gnus-set-global-variables)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe))
-    (gnus-summary-save-article arg))
+    (gnus-summary-save-article arg t))
   (gnus-configure-windows 'pipe))
 
 (defun gnus-summary-save-article-mail (&optional arg)
@@ -11653,27 +11897,38 @@ save those articles instead."
 
 (defun gnus-read-save-file-name (prompt default-name)
   (let ((methods gnus-split-methods)
-       split-name method)
+       split-name method result match)
     ;; Let the split methods have their say.
     (when gnus-split-methods
       (save-excursion
        (set-buffer gnus-original-article-buffer)
-       (gnus-narrow-to-headers)
-       (while methods
-         (goto-char (point-min))
-         (setq method (pop methods))
-         (when (cond ((stringp (car method))
-                      (condition-case () 
-                          (re-search-forward (car method) nil t)
-                        (error nil)))
-                     ((gnus-functionp (car method))
-                      (funcall (car method)))
-                     ((consp (car method))
-                      (eval (car method))))
-           (setq split-name (cons (nth 1 methods) split-name))))
-       (widen)))
+       (save-restriction
+         (gnus-narrow-to-headers)
+         (while methods
+           (goto-char (point-min))
+           (setq method (pop methods))
+           (setq match (pop method))
+           (when (cond
+                  ((stringp match)
+                   ;; Regular expression.
+                   (condition-case () 
+                       (re-search-forward match nil t)
+                     (error nil)))
+                  ((gnus-functionp match)
+                   (save-restriction
+                     (widen)
+                     (setq result (funcall match gnus-newsgroup-name))))
+                  ((consp match)
+                   (save-restriction
+                     (widen)
+                     (setq result (eval match)))))
+             (setq split-name (append (cdr methods) split-name))
+             (cond ((stringp result)
+                    (push result split-name))
+                   ((consp result)
+                    (setq split-name (append result split-name)))))))))
     (cond
-     ;; No split name was found
+     ;; No split name was found.
      ((null split-name)
       (read-file-name
        (concat prompt " (default " (file-name-nondirectory default-name) ") ")
@@ -11694,6 +11949,12 @@ save those articles instead."
                    (car (car split-name))
                  result)))))))
 
+(defun gnus-article-archive-name (group)
+  "Return the first instance of an \"Archive-name\" in the current buffer."
+  (let ((case-fold-search t))
+    (when (re-search-forward "archive-name: *\\([^ \n\t]+\\)[ \t]*$" nil t)
+      (match-string 1))))
+
 (defun gnus-summary-save-in-rmail (&optional filename)
   "Append this article to Rmail file.
 Optional argument FILENAME specifies file name.
@@ -11966,6 +12227,7 @@ is initialized from the SAVEDIR environment variable."
   (define-key gnus-article-mode-map gnus-mouse-2 'gnus-article-push-button)
   (define-key gnus-article-mode-map "\r" 'gnus-article-press-button)
   (define-key gnus-article-mode-map "\t" 'gnus-article-next-button)
+  (define-key gnus-article-mode-map "\M-\t" 'gnus-article-prev-button)
   (define-key gnus-article-mode-map "\C-c\C-b" 'gnus-bug)
   
   ;; Duplicate almost all summary keystrokes in the article mode map.
@@ -12371,12 +12633,23 @@ Provided for backwards compatability."
 (defun gnus-article-hide-headers (&optional delete)
   "Hide unwanted headers and possibly sort them as well."
   (interactive "P")
+  ;; This function might be inhibited.
   (unless gnus-inhibit-hiding
     (save-excursion
       (set-buffer gnus-article-buffer)
       (save-restriction
-       (let ((sorted gnus-sorted-header-list)
-             (buffer-read-only nil)
+       (let ((buffer-read-only nil)
+             (ignored (when (not (stringp gnus-visible-headers))
+                        (cond ((stringp gnus-ignored-headers)
+                               gnus-ignored-headers)
+                              ((listp gnus-ignored-headers)
+                               (mapconcat 'identity gnus-ignored-headers
+                                          "\\|")))))
+             (visible (cond ((stringp gnus-visible-headers)
+                             gnus-visible-headers)
+                            ((listp gnus-visible-headers)
+                             (mapconcat 'identity gnus-visible-headers
+                                        "\\|"))))
              want-list beg want-l)
          ;; First we narrow to just the headers.
          (widen)
@@ -12384,8 +12657,8 @@ Provided for backwards compatability."
          ;; Hide any "From " lines at the beginning of (mail) articles. 
          (while (looking-at "From ")
            (forward-line 1))
-         (or (bobp) 
-             (add-text-properties (point-min) (point) gnus-hidden-properties))
+         (unless (bobp) 
+           (add-text-properties (point-min) (point) gnus-hidden-properties))
          ;; Then treat the rest of the header lines.
          (narrow-to-region 
           (point) 
@@ -12399,47 +12672,48 @@ Provided for backwards compatability."
            (beginning-of-line)
            ;; We add the headers we want to keep to a list and delete
            ;; them from the buffer.
-           (if (or (and (stringp gnus-visible-headers)
-                        (looking-at gnus-visible-headers))
-                   (and (not (stringp gnus-visible-headers))
-                        (stringp gnus-ignored-headers)
-                        (not (looking-at gnus-ignored-headers))))
+           (if (or (and visible (looking-at visible))
+                   (and ignored (not (looking-at ignored))))
                (progn
-                 (setq beg (point))
-                 (forward-line 1)
-                 ;; Be sure to get multi-line headers...
-                 (re-search-forward "^[^ \t]*:" nil t)
-                 (beginning-of-line)
-                 (setq want-list 
-                       (cons (buffer-substring beg (point)) want-list))
-                 (delete-region beg (point))
-                 (goto-char beg))
+                 (push (buffer-substring
+                        (setq beg (point))
+                        (progn 
+                          (forward-line 1)
+                          ;; Be sure to get multi-line headers...
+                          (re-search-forward "^[^ \t]*:" nil t)
+                          (beginning-of-line) 
+                          (point)))
+                       want-list)
+                 (delete-region beg (point)))
              (forward-line 1)))
-         ;; Next we perform the sorting by looking at
-         ;; `gnus-sorted-header-list'. 
+         ;; Sort the headers that we want to display.
+         (setq want-list (sort want-list 'gnus-article-header-less))
          (goto-char (point-min))
-         (while (and sorted want-list)
-           (setq want-l want-list)
-           (while (and want-l
-                       (not (string-match (car sorted) (car want-l))))
-             (setq want-l (cdr want-l)))
-           (if want-l 
-               (progn
-                 (insert (car want-l))
-                 (setq want-list (delq (car want-l) want-list))))
-           (setq sorted (cdr sorted)))
-         ;; Any headers that were not matched by the sorted list we
-         ;; just tack on the end of the visible header list.
          (while want-list
-           (insert (car want-list))
-           (setq want-list (cdr want-list)))
-         ;; And finally we make the unwanted headers invisible.
+           (insert (pop want-list)))
+         ;; We make the unwanted headers invisible.
          (if delete
-             (delete-region (point) (point-max))
+             (delete-region (point-min) (point-max))
            ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
            (add-text-properties 
             (point) (point-max) gnus-hidden-properties)))))))
 
+(defsubst gnus-article-header-rank (header)
+  "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
+  (let ((list gnus-sorted-header-list)
+       (i 0))
+    (while list
+      (when (string-match (car list) header)
+       (setq list nil))
+      (setq list (cdr list))
+      (incf i))
+    i))
+
+(defun gnus-article-header-less (h1 h2)
+  "Say whether string H1 is \"less\" than string H2."
+  (< (gnus-article-header-rank h1)
+     (gnus-article-header-rank h2)))
+
 ;; Written by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defun gnus-article-treat-overstrike ()
   "Translate overstrikes into bold text."
@@ -12633,10 +12907,11 @@ or not."
 If TYPE is `local', convert to local time; if it is `lapsed', output
 how much time has lapsed since DATE."
   (interactive (list 'ut t))
-  (let ((date (mail-header-date (or gnus-current-headers 
-                                   (gnus-summary-article-header) "")))
-       (date-regexp "^Date: \\|^X-Sent: ")
-       (inhibit-point-motion-hooks t))
+  (let* ((header (or gnus-current-headers 
+                    (gnus-summary-article-header) ""))
+        (date (and (vectorp header) (mail-header-date header)))
+        (date-regexp "^Date: \\|^X-Sent: ")
+        (inhibit-point-motion-hooks t))
     (when (and date (not (string= date "")))
       (save-excursion
        (set-buffer gnus-article-buffer)
@@ -12823,57 +13098,31 @@ function and want to see what the date was before converting."
     (insert "\^_")))
 
 (defun gnus-narrow-to-page (&optional arg)
-  "Make text outside current page invisible except for page delimiter.
-A numeric arg specifies to move forward or backward by that many pages,
-thus showing a page other than the one point was originally in."
+  "Narrow the article buffer to a page.
+If given a numerical ARG, move forward ARG pages."
   (interactive "P")
   (setq arg (if arg (prefix-numeric-value arg) 0))
   (save-excursion
-    (forward-page -1)                  ;Beginning of current page.
+    (set-buffer gnus-article-buffer)
+    (goto-char (point-min))
     (widen)
-    (if (> arg 0)
-       (forward-page arg)
-      (if (< arg 0)
-         (forward-page (1- arg))))
-    ;; Find the end of the page.
-    (forward-page)
-    ;; If we stopped due to end of buffer, stay there.
-    ;; If we stopped after a page delimiter, put end of restriction
-    ;; at the beginning of that line.
-    ;; These are commented out.
-    ;;    (if (save-excursion (beginning-of-line)
-    ;;                 (looking-at page-delimiter))
-    ;; (beginning-of-line))
-    (narrow-to-region (point)
-                     (progn
-                       ;; Find the top of the page.
-                       (forward-page -1)
-                       ;; If we found beginning of buffer, stay there.
-                       ;; If extra text follows page delimiter on same line,
-                       ;; include it.
-                       ;; Otherwise, show text starting with following line.
-                       (if (and (eolp) (not (bobp)))
-                           (forward-line 1))
-                       (point)))))
-
-(defun gnus-gmt-to-local ()
-  "Rewrite Date header described in GMT to local in current buffer.
-Intended to be used with gnus-article-prepare-hook."
-  (save-excursion
-    (save-restriction
-      (widen)
-      (goto-char (point-min))
-      (narrow-to-region (point-min)
-                       (progn (search-forward "\n\n" nil 'move) (point)))
-      (goto-char (point-min))
-      (if (re-search-forward "^Date:[ \t]\\(.*\\)$" nil t)
-         (let ((buffer-read-only nil)
-               (date (buffer-substring-no-properties
-                      (match-beginning 1) (match-end 1))))
-           (delete-region (match-beginning 1) (match-end 1))
-           (insert
-            (timezone-make-date-arpa-standard 
-             date nil (current-time-zone))))))))
+    (when 
+       (cond ((< arg 0)
+              (re-search-backward page-delimiter nil 'move (1+ (abs arg))))
+             ((> arg 0)
+              (re-search-forward page-delimiter nil 'move arg)))
+      (goto-char (match-end 0)))
+    (when (and (gnus-visual-p 'page-marker)
+              (not (bolp)))
+      (gnus-insert-prev-page-button))
+    (narrow-to-region
+     (point)
+     (if (re-search-forward page-delimiter nil 'move)
+        (prog1 (match-beginning 0) 
+          (when (and (gnus-visual-p 'page-marker)
+                     (not (bolp)))
+            (gnus-insert-next-page-button)))
+       (point)))))
 
 ;; Article mode commands
 
@@ -12916,7 +13165,9 @@ Argument LINES specifies lines to be scrolled down."
        (gnus-narrow-to-page -1)        ;Go to previous page.
        (goto-char (point-max))
        (recenter -1))
-    (scroll-down lines)))
+    (condition-case ()
+       (scroll-down lines)
+      (error nil))))
 
 (defun gnus-article-refer-article ()
   "Read article specified by message-id around point."
@@ -13334,7 +13585,7 @@ ARTICLES is the `data' of the group."
 If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
   (let ((method (gnus-find-method-for-group group)))
     (if (and gnus-use-cache (numberp (car articles)))
-       (gnus-cache-retrieve-headers articles group)
+       (gnus-cache-retrieve-headers articles group fetch-old)
       (funcall (gnus-get-function method 'retrieve-headers) 
               articles (gnus-group-real-name group) (nth 1 method)
               fetch-old))))
@@ -13346,7 +13597,7 @@ If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
 (defun gnus-request-type (group &optional article)
   "Return the type (`post' or `mail') of GROUP (and ARTICLE)."
   (let ((method (gnus-find-method-for-group group)))
-    (if (not (gnus-check-backend-function 'request-type method))
+    (if (not (gnus-check-backend-function 'request-type (car method)))
        'unknown
       (funcall (gnus-get-function method 'request-type)
               (gnus-group-real-name group) article))))
@@ -13603,7 +13854,7 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
 
     ;; Find the number of unread articles in each non-dead group.
     (let ((gnus-read-active-file (and (not level) gnus-read-active-file)))
-      (gnus-get-unread-articles (or level (1+ gnus-level-subscribed))))
+      (gnus-get-unread-articles level))
 
     (if (and init gnus-check-bogus-newsgroups 
             gnus-read-active-file (not level)
@@ -13970,7 +14221,7 @@ newsgroup."
 ;; and compute how many unread articles there are in each group.
 (defun gnus-get-unread-articles (&optional level) 
   (let* ((newsrc (cdr gnus-newsrc-alist))
-        (level (or level (1+ gnus-level-subscribed)))
+        (level (or level gnus-activate-level (1+ gnus-level-subscribed)))
         (foreign-level
          (min 
           (cond ((and gnus-activate-foreign-newsgroups 
index 100b40f..c1ac47d 100644 (file)
@@ -128,29 +128,29 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf',
 ;;; Interface functions
 
 (defun nndoc-retrieve-headers (articles &optional newsgroup server fetch-old)
-  (nndoc-possibly-change-buffer newsgroup server)
-  (save-excursion
-    (set-buffer nntp-server-buffer)
-    (erase-buffer)
-    (let (article entry)
-      (if (stringp (car articles))
-         'headers
-       (while articles
-         (setq entry (cdr (assq (setq article (pop articles))
-                                nndoc-dissection-alist)))
-         (insert (format "221 %d Article retrieved.\n" article))
-         (insert-buffer-substring
-          nndoc-current-buffer (car entry) (nth 1 entry))
-         (goto-char (point-max))
-         (or (= (char-after (1- (point))) ?\n) (insert "\n"))
-         (insert (format "Lines: %d\n" (nth 4 entry)))
-         (insert ".\n"))
-
-       ;; Fold continuation lines.
-       (goto-char (point-min))
-       (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-         (replace-match " " t t))
-       'headers))))
+  (when (nndoc-possibly-change-buffer newsgroup server)
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (let (article entry)
+       (if (stringp (car articles))
+           'headers
+         (while articles
+           (setq entry (cdr (assq (setq article (pop articles))
+                                  nndoc-dissection-alist)))
+           (insert (format "221 %d Article retrieved.\n" article))
+           (insert-buffer-substring
+            nndoc-current-buffer (car entry) (nth 1 entry))
+           (goto-char (point-max))
+           (or (= (char-after (1- (point))) ?\n) (insert "\n"))
+           (insert (format "Lines: %d\n" (nth 4 entry)))
+           (insert ".\n"))
+
+         ;; Fold continuation lines.
+         (goto-char (point-min))
+         (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
+           (replace-match " " t t))
+         'headers)))))
 
 (defun nndoc-open-server (server &optional defs)
   (nnheader-init-server-buffer)
@@ -277,12 +277,12 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf',
        (if (stringp nndoc-address)
            (insert-file-contents nndoc-address)
          (insert-buffer-substring nndoc-address)))))
-    (save-excursion
-      (set-buffer nndoc-current-buffer)
-      (nndoc-set-delims)
-      (nndoc-dissect-buffer))
-    t))
-
+    (when nndoc-current-buffer
+      (save-excursion
+       (set-buffer nndoc-current-buffer)
+       (nndoc-set-delims)
+       (nndoc-dissect-buffer))
+      t)))
 
 ;; MIME (RFC 1341) digest hack by Ulrik Dickow <dickow@nbi.dk>.
 (defun nndoc-guess-digest-type ()
@@ -427,8 +427,7 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf',
 (defun nndoc-rnews-body-end ()
   (save-excursion
     (and (re-search-backward nndoc-article-begin nil t)
-        (goto-char (+ (point) (string-to-int (match-string 1)))))))
-  
+        (goto-char (+ (point) (string-to-int (match-string 1)))))))  
 
 (provide 'nndoc)
 
index 1d490d1..12bc292 100644 (file)
@@ -221,26 +221,21 @@ such things as moving mail.  All buffers always get killed upon server close.")
 (defun nnfolder-request-group (group &optional server dont-check)
   (save-excursion
     (nnmail-activate 'nnfolder)
-    (nnfolder-possibly-change-group group)
-    (and (assoc group nnfolder-group-alist)
-        (progn
-          (if dont-check
-              t
-            (let* ((active (assoc group nnfolder-group-alist))
-                   (group (car active))
-                   (range (car (cdr active)))
-                   (minactive (car range))
-                   (maxactive (cdr range)))
-              ;; I've been getting stray 211 lines in my nnfolder active
-              ;; file.  So, let's make sure that doesn't happen. -SLB
-              (set-buffer nntp-server-buffer)
-              (erase-buffer)
-              (if (not active)
-                  ()
-                (insert (format "211 %d %d %d %s\n" 
-                                (1+ (- maxactive minactive))
-                                minactive maxactive group))
-                t)))))))
+    (when (assoc group nnfolder-group-alist)
+      (if dont-check
+         t
+       (let* ((active (assoc group nnfolder-group-alist))
+              (group (car active))
+              (range (car (cdr active)))
+              (minactive (car range))
+              (maxactive (cdr range)))
+         (set-buffer nntp-server-buffer)
+         (erase-buffer)
+         (when active
+           (insert (format "211 %d %d %d %s\n" 
+                           (1+ (- maxactive minactive))
+                           minactive maxactive group))
+           t))))))
 
 (defun nnfolder-request-scan (&optional group server)
   (nnmail-get-new-mail
index 6a8ad98..901643c 100644 (file)
@@ -394,6 +394,32 @@ Return the number of headers removed."
   (buffer-disable-undo (current-buffer))
   (erase-buffer))
 
+(defvar jka-compr-compression-info-list)
+(defvar nnheader-numerical-files
+  (if (boundp 'jka-compr-compression-info-list)
+      (concat "\\([0-9]+\\)\\(" 
+             (mapconcat (lambda (i) (aref i 0))
+                        jka-compr-compression-info-list "\\|")
+             "\\)?")
+    "[0-9]+$")
+  "Regexp that match numerical files.")
+
+(defvar nnheader-numerical-short-files (concat "^" nnheader-numerical-files)
+  "Regexp that matches numerical file names.")
+
+(defvar nnheader-numerical-full-files (concat "/" nnheader-numerical-files)
+  "Regexp that matches numerical full file paths.")
+
+(defun nnheader-file-to-number (file)
+  (if (not (boundp 'jka-compr-compression-info-list))
+      (string-to-int file)
+    (string-match nnheader-numerical-short-files file)
+    (match-string 1 file)))
+
+(defun nnheader-directory-articles (dir)
+  (mapcar 'nnheader-file-to-number
+         (directory-files dir nil nnheader-numerical-short-files t)))
+
 (provide 'nnheader)
 
 ;;; nnheader.el ends here
index 681b006..c7fb006 100644 (file)
@@ -190,6 +190,19 @@ If the stream is opened, return T, otherwise return NIL."
 
 (defalias 'nnkiboze-request-post 'nntp-request-post)
 
+(defun nnkiboze-request-delete-group (group &optional force server)
+  (nnkiboze-possibly-change-newsgroups group)
+  (when force
+     (let ((files (list (nnkiboze-nov-file-name)
+                       (concat nnkiboze-directory group ".newsrc")
+                       (nnkiboze-score-file group))))
+       (while files
+        (and (file-exists-p (car files))
+             (file-writable-p (car files))
+             (delete-file (car files)))
+        (setq files (cdr files)))))
+  (setq nnkiboze-current-group nil))
+
 \f
 ;;; Internal functions.
 
index e2ce469..19c75e5 100644 (file)
@@ -300,9 +300,13 @@ perfomed.")
 
 (defun nnmail-days-to-time (days)
   "Convert DAYS into time."
-  (let ((seconds (round (* days 60 60 24)))
+  (let ((seconds (* 1.0 days 60 60 24))
        (rest (expt 2 16)))
-  (list (/ seconds rest) (% seconds rest))))
+    (list (round (/ seconds rest))
+         ;;;!!!Error error error.  I'm not a mathematician, though.
+         (condition-case ()
+             (% (round seconds) rest)
+           (error 0)))))
 
 (defun nnmail-time-since (time)
   "Return the time since DATE."
@@ -840,12 +844,10 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
                                        (file-truename nnmail-crash-box))) 0))
                    (list nnmail-crash-box))))
       ;; Remove any directories that inadvertantly match the procmail
-      ;; suffix, which might happen if the suffix is "".  We also
-      ;; ditch symlinks. 
+      ;; suffix, which might happen if the suffix is "". 
       (while p
-       (and (or (file-directory-p (car p))
-                (file-symlink-p (car p)))
-            (setq procmails (delete (car p) procmails)))
+       (when (file-directory-p (car p))
+         (setq procmails (delete (car p) procmails)))
        (setq p (cdr p)))
       ;; Return the list of spools.
       (append 
index 2aaa0b5..46e6fcd 100644 (file)
@@ -70,6 +70,8 @@ all. This may very well take some time.")
 (defvar nnml-group-alist nil)
 (defvar nnml-active-timestamp nil)
 
+(defvar nnml-generate-active-function 'nnml-generate-active-info)
+
 \f
 
 ;; Server variables.
@@ -231,11 +233,8 @@ all. This may very well take some time.")
                                     nnml-group-alist))
        (nnml-possibly-create-directory group)
        (nnml-possibly-change-directory group)
-       (let ((articles (mapcar
-                        (lambda (file)
-                          (string-to-int file))
-                        (directory-files 
-                         nnml-current-directory nil "^[0-9]+$"))))
+       (let ((articles 
+              (nnheader-directory-articles nnml-current-directory )))
          (and articles
               (progn
                 (setcar active (apply 'min articles))
@@ -261,11 +260,7 @@ all. This may very well take some time.")
 (defun nnml-request-expire-articles (articles newsgroup &optional server force)
   (nnml-possibly-change-directory newsgroup)
   (let* ((active-articles 
-         (mapcar
-          (function
-           (lambda (name)
-             (string-to-int name)))
-          (directory-files nnml-current-directory nil "^[0-9]+$" t)))
+         (nnheader-directory-articles nnml-current-directory))
         (max-article (and active-articles (apply 'max active-articles)))
         (is-old t)
         article rest mod-time number)
@@ -386,21 +381,20 @@ all. This may very well take some time.")
 
 (defun nnml-request-delete-group (group &optional force server)
   (nnml-possibly-change-directory group)
-  ;; Delete all articles in GROUP.
-  (if (not force)
-      ()                               ; Don't delete the articles.
+  (when force
+    ;; Delete all articles in GROUP.
     (let ((articles 
           (directory-files 
            nnml-current-directory t
-           (concat "^[0-9]+$\\|" (regexp-quote nnml-nov-file-name) "$"))))
+           (concat nnheader-numerical-short-files
+                   "\\|" (regexp-quote nnml-nov-file-name) "$")))
+         article)
       (while articles 
-       (and (file-writable-p (car articles))
-            (progn
-              (and gnus-verbose-backends
-                   (message (message "Deleting article %s in %s..."
-                                     (car articles) group)))
-              (funcall nnmail-delete-file-function (car articles))))
-       (setq articles (cdr articles))))
+       (setq article (pop articles))
+       (when (file-writable-p article)
+         (when gnus-verbose-backends
+           (message "Deleting article %s in %s..." article group))
+         (funcall nnmail-delete-file-function article))))
     ;; Try to delete the directory itself.
     (condition-case ()
        (delete-directory nnml-current-directory)
@@ -685,75 +679,90 @@ all. This may very well take some time.")
       (setq nnml-nov-buffer-alist (cdr nnml-nov-buffer-alist)))))
 
 ;;;###autoload
-(defun nnml-generate-nov-databases (dir)
+(defun nnml-generate-nov-databases ()
   "Generate nov databases in all nnml directories."
-  (interactive 
-   (progn   
-     (setq nnml-group-alist nil)
-     (list nnml-directory)))
+  (interactive)
+  ;; Read the active file to make sure we don't re-use articles 
+  ;; numbers in empty groups.
+  (nnmail-activate 'nnml)
   (nnml-open-server (or nnml-current-server ""))
-  (let ((dirs (directory-files dir t nil t)))
+  (setq nnml-directory (expand-file-name nnml-directory))
+  ;; Recurse down the directories.
+  (nnml-generate-nov-databases-1 nnml-directory)
+  ;; Save the active file.
+  (nnmail-save-active nnml-group-alist nnml-active-file))
+
+(defun nnml-generate-nov-databases-1 (dir)
+  (setq dir (file-name-as-directory dir))
+  ;; We descend recursively 
+  (let ((dirs (directory-files dir t nil t))
+       dir)
     (while dirs 
-      (if (and (not (string-match "/\\.\\.$" (car dirs)))
-              (not (string-match "/\\.$" (car dirs)))
-              (file-directory-p (car dirs)))
-         (nnml-generate-nov-databases (car dirs)))
-      (setq dirs (cdr dirs))))
+      (setq dir (pop dirs))
+      (when (and (not (string-match "/\\.\\.?$" dir))
+                (file-directory-p dir))
+       (nnml-generate-nov-databases-1 dir))))
+  ;; Do this directory.
   (let ((files (sort
                (mapcar
-                (function
-                 (lambda (name)
-                   (string-to-int name)))
+                (lambda (name) (string-to-int name))
                 (directory-files dir nil "^[0-9]+$" t))
-               (function <)))
-       (nov (concat dir "/" nnml-nov-file-name))
-       (nov-buffer (get-buffer-create "*nov*"))
+               '<)))
+    (when files
+      (funcall nnml-generate-active-function dir)
+      ;; Generate the nov file.
+      (nnml-generate-nov-file dir files))))
+
+(defun nnml-generate-active-info (dir)
+  ;; Update the active info for this group.
+  (let ((group (nnmail-replace-chars-in-string 
+               (substring dir (length nnml-directory))
+               ?/ ?.)))
+    (setq nnml-group-alist (delq (assoc group nnml-group-alist)))
+    (push (list group
+               (cons (car files)
+                     (let ((f files))
+                       (while (cdr f) (setq f (cdr f)))
+                       (car f))))
+         nnml-group-alist)))
+
+(defun nnml-generate-nov-file (dir files)
+  (let ((nov (concat dir "/" nnml-nov-file-name))
+       (nov-buffer (get-buffer-create " *nov*"))
        nov-line chars)
-    (if files
-       (setq nnml-group-alist 
-             (cons (list (nnmail-replace-chars-in-string 
-                          (substring (expand-file-name dir)
-                                     (length (expand-file-name 
-                                              nnml-directory)))
-                          ?/ ?.)
-                         (cons (car files)
-                               (let ((f files))
-                                 (while (cdr f) (setq f (cdr f)))
-                                 (car f))))
-                   nnml-group-alist)))
-    (if files
-       (save-excursion
-         (set-buffer nntp-server-buffer)
-         (if (file-exists-p nov)
-             (funcall nnmail-delete-file-function nov))
-         (save-excursion
-           (set-buffer nov-buffer)
-           (buffer-disable-undo (current-buffer))
-           (erase-buffer))
-         (while files
-           (erase-buffer)
-           (insert-file-contents (concat dir "/" (int-to-string (car files))))
-           (narrow-to-region 
-            (goto-char (point-min))
-            (save-excursion
-              (search-forward "\n\n" nil t)
-              (setq chars (- (point-max) (point)))
-              (point)))
-           (when (and (not (= 0 chars))        ; none of them empty files...
-                      (not (= (point-min) (point-max))))
-             (setq nov-line (nnml-make-nov-line chars))
-             (save-excursion
-               (set-buffer nov-buffer)
-               (goto-char (point-max))
-               (insert (int-to-string (car files)) nov-line)))
-           (widen)
-           (setq files (cdr files)))
+    (save-excursion
+      ;; Init the nov buffer.
+      (set-buffer nov-buffer)
+      (buffer-disable-undo (current-buffer))
+      (erase-buffer)
+      (set-buffer nntp-server-buffer)
+      ;; Delete the old NOV file.
+      (when (file-exists-p nov)
+       (funcall nnmail-delete-file-function nov))
+      (while files
+       (erase-buffer)
+       (insert-file-contents (concat dir "/" (int-to-string (car files))))
+       (narrow-to-region 
+        (goto-char (point-min))
+        (progn
+          (search-forward "\n\n" nil t)
+          (setq chars (- (point-max) (point)))
+          (1- (point))))
+       (when (and (not (= 0 chars))    ; none of them empty files...
+                  (not (= (point-min) (point-max))))
+         (goto-char (point-min))
+         (setq nov-line (nnml-make-nov-line chars))
          (save-excursion
            (set-buffer nov-buffer)
-           (write-region 1 (point-max) (expand-file-name nov) nil
-                         'nomesg)
-           (kill-buffer (current-buffer)))))
-    (nnmail-save-active nnml-group-alist nnml-active-file)))
+           (goto-char (point-max))
+           (insert (int-to-string (car files)) nov-line)))
+       (widen)
+       (setq files (cdr files)))
+      (save-excursion
+       (set-buffer nov-buffer)
+       (write-region 1 (point-max) (expand-file-name nov) nil
+                     'nomesg)
+       (kill-buffer (current-buffer))))))
 
 (defun nnml-nov-delete-article (group article)
   (save-excursion
index d77d9a4..0c763c4 100644 (file)
@@ -613,6 +613,15 @@ It will make innd servers spawn an nnrpd process to allow actual article
 reading."
   (nntp-send-command "^.*\r?\n" "MODE READER"))
 
+(defun nntp-send-nosy-authinfo ()
+  "Send the AUTHINFO to the nntp server.
+This function is supposed to be called from `nntp-server-opened-hook'.
+It will prompt for a password."
+  (nntp-send-command "^.*\r?\n" "AUTHINFO USER"
+                    (read-string "NNTP user name: "))
+  (nntp-send-command "^.*\r?\n" "AUTHINFO PASS" 
+                    (read-string "NNTP password: ")))
+
 (defun nntp-send-authinfo ()
   "Send the AUTHINFO to the nntp server.
 This function is supposed to be called from `nntp-server-opened-hook'.
index 2e62d19..c20dc3e 100644 (file)
@@ -1,3 +1,33 @@
+Wed Dec 13 16:13:56 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Selecting a Group): Addition.
+       (Saving Articles): Addition.
+       (Score File Format): Addition.
+
+Tue Dec 12 11:04:14 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Other Marks): Addition; change.
+       (Exiting the Summary Buffer): Addition.
+       (Hiding Headers): Addition.
+       (Score File Format): Addition.
+       (Article Caching): Addition.
+       (Misc Group Stuff): Addition.
+
+Mon Dec 11 09:52:34 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Persistent Articles): New.
+       (Other Marks): Addition.
+       (Topic Variables): Deletia.
+       (New Groups): Addition.
+       (Subscription Commands): Addition.
+       (Selecting a Group): Addition.
+       (Viewing Files): Addition.
+       (Group Levels): Addition.
+
+Sun Dec 10 13:51:16 1995  Lars Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (The Active File): Change.
+
 Sat Dec  9 16:55:29 1995  Lars Ingebrigtsen  <lars@eyesore.no>
 
        * gnus.texi (nndoc): Change.
index 42e4535..742a4d9 100644 (file)
@@ -17,3 +17,6 @@ refcard.dvi: refcard.tex
 
 clean:
        rm -f gnus.*.bak gnus.ky gnus.cp gnus.aux gnus.fn gnus.dvi gnus.cps gnus.kys gnus.log gnus.pg gnus.tp gnus.vr gnus.toc
+
+makeinfo: 
+       makeinfo -o gnus.info gnus.texi 
index 052d7b9..143c7b5 100644 (file)
@@ -491,6 +491,9 @@ All Gnus buffers can be customized in a difficult fashion
 You can click on buttons instead of using the keyboard
 (@pxref{Buttons}). 
 
+@item 
+Gnus can use NoCeM files to weed out spam (@pxref{NoCeM}). 
+
 @end itemize
 
 This is, of course, just a @emph{short} overview of the @emph{most}
@@ -516,12 +519,8 @@ Native @sc{mime} support is something that should be done.
 @item
 @code{nn}-like pick-and-read summary interface.
 @item 
-NoCeM support.
-@item 
 Frame configuration.
 @item 
-Floating point group levels and group bubbling.
-@item 
 Automatic re-scan of incoming mail.
 @item
 Buttonize more stuff in the article buffer.
@@ -529,8 +528,6 @@ Buttonize more stuff in the article buffer.
 A better and simpler method for specifying mail composing methods. 
 @item 
 Marks for saved, forwarded, etc articles.
-@item 
-Speed up caching and adaptive scoring.
 @item
 Gather thread by filling in missing Message-IDs.
 @item 
@@ -538,26 +535,16 @@ PGP support.
 @item
 Allow posting through mail-to-news gateways.
 @item
-Speed up massive group massacres.
-@item
 @code{jka-compr} isn't fully supported.
 @item
-Create better digests.
-@item
 Do better word-wrap on cited text.
 @item 
 Better X-Face support with X-Face databases and stuff. 
 @item
-Support SELF-DISCIPLINE pins.
-@item
 Really do unbinhexing.
 @item
-Listing of all active groups.
-@item
 XEmacs toolbar.
 @item
-Do the X-Receipt-To thing.
-@item
 Don't kill summary buffers upon exit from the groups.
 @item
 Allow adaption on secondary marks.
@@ -570,6 +557,7 @@ implemented.  (But that's always true, isn't it?)
 up-to-the-second todo list is located, so if you're really curious, you
 could point your Web browser over that-a-way.
 
+
 @node Terminology
 @chapter Terminology
 
@@ -868,6 +856,10 @@ Subscribe all new groups hierarchically.
 Subscribe new groups interactively.  This means that Gnus will ask
 you about @strong{all} new groups.
 
+@item gnus-subscribe-killed
+@vindex gnus-subscribe-killed
+Kill all new groups.
+
 @item gnus-subscribe-zombies
 @vindex gnus-subscribe-zombies
 Make all new groups zombies.  You can browse the zombies later (with
@@ -1039,9 +1031,10 @@ server.
 Before examining the active file, Gnus deletes all lines that match the
 regexp @code{gnus-ignored-newsgroups}.  This is done primarily to reject
 any groups with bogus names, but you can use this variable to make Gnus
-ignore hierarchies you aren't ever interested in.  This variable is
-@code{nil} by default, and will slow down active file handling somewhat
-if you set it to anything else.
+ignore hierarchies you aren't ever interested in.  
+@c This variable is
+@c @code{nil} by default, and will slow down active file handling somewhat
+@c if you set it to anything else.
 
 @vindex gnus-read-active-file
 The active file can be rather Huge, so if you have a slow network, you
@@ -1238,9 +1231,9 @@ format specifiers:
 
 @table @samp
 @item S
-Default news server.
+The native news server.
 @item M
-Default select method.
+The native select method.
 @end table
 
 @node Group Maneuvering
@@ -1346,6 +1339,13 @@ scoring/killing will be performed, there will be no highlights and no
 expunging.  This might be useful if you're in a real hurry and have to
 enter some humongous groups.
 
+@item M-SPACE
+@kindex M-RET (Group)
+@findex gnus-group-visible-select-group
+This is yet one more command that does the same as the one above, but
+this one does it without expunging and hiding dormants
+(@code{gnus-group-visible-select-group}).  
+
 @item c
 @kindex c (Group)
 @findex gnus-group-catchup-current
@@ -1403,7 +1403,7 @@ 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-date}, @code{gnus-thread-sort-by-score}, and
 @code{gnus-thread-sort-by-total-score}.
 
 Each function takes two threads and return non-@code{nil} if the first
@@ -1426,6 +1426,20 @@ The function in the @code{gnus-thread-score-function} variable (default
 functions might be @code{max}, @code{min}, or squared means, or whatever
 tickles you fancy.
 
+@findex gnus-article-sort-functions
+@findex gnus-article-sort-by-date
+@findex gnus-article-sort-by-score
+@findex gnus-article-sort-by-subject
+@findex gnus-article-sort-by-author
+@findex gnus-article-sort-by-number
+If you are using an unthreaded display for some strange reason or other,
+you have to fiddle with the @code{gnus-article-sort-functions}
+variable.  It is very similar to the @code{gnus-thread-sort-functions},
+except that is uses slightly different functions for article
+comparison.  Available functions are @code{gnus-article-sort-by-number},
+@code{gnus-article-sort-by-author}, @code{gnus-article-sort-by-subject},
+@code{gnus-article-sort-by-date}, and @code{gnus-article-sort-by-score}.
+
 
 @node Subscription Commands
 @section Subscription Commands
@@ -1469,6 +1483,17 @@ Kill all groups in the region (@code{gnus-group-kill-region}).
 @kindex S z (Group)
 @findex gnus-group-kill-all-zombies
 Kill all zombie groups (@code{gnus-group-kill-all-zombies}).
+@item S C-k
+@kindex S C-k (Group)
+@findex gnus-group-kill-level
+Kill all groups on a certain level (@code{gnus-group-kill-level}).
+These groups can't be yanked back after killing, so this command should
+be used with some caution.  The only thing where this command comes in
+really handy is when you have a @file{.newsrc} with lots of unsubscribed
+groups that you want to get rid off.  @kbd{S C-k} on level @code{7} will
+kill off all unsubscribed groups that do not have message numbers in the
+@file{.newsrc} file.  
+
 @end table
 
 Also @xref{Group Levels}.
@@ -1541,6 +1566,12 @@ If @code{gnus-group-use-permament-levels} is non-@code{nil}, once you
 give a level prefix to @kbd{g} or @kbd{l}, all subsequent commands will
 use this level as the "work" level.
 
+@vindex gnus-activate-level
+Gnus will normally just activate groups that are on level
+@code{gnus-activate-level} or less.  If you don't want to activate
+unsubscribed groups, for instance, you might set this variable to
+@samp{5}. 
+
 
 @node Group Score
 @section Group Score
@@ -1721,8 +1752,8 @@ Make a group based on some file or other
 (@code{gnus-group-make-doc-group}).  If you give a prefix to this
 command, you will be prompted for a file name and a file type.
 Currently supported types are @code{babyl}, @code{mbox}, @code{digest},
-@code{mmdf}, and @code{forward}.  If you run this command without a
-prefix, Gnus will guess at the file type.
+@code{mmdf}, @code{news}, @code{rnews}, and @code{forward}.  If you run
+this command without a prefix, Gnus will guess at the file type.
 
 @item G DEL
 @kindex G DEL (Group)
@@ -2161,12 +2192,45 @@ Name of the map files.
 @cindex help group
 
 @code{nndoc} is a cute little thing that will let you read a single file
-as a newsgroup.  Currently supported file types are @code{babyl} (the
-RMAIL file type), @code{mbox} (standard Unix mbox files), @code{digest}
-(various digests, MIME and otherwise), @code{mmdf} (the MMDF mail box
-format), and @code{forward} (a single forwarded mail).  You can also use
-the special "file type" @code{guess}, which means that @code{nndoc} will
-try to guess what file type it is looking at.
+as a newsgroup.  Several files types are supported:
+
+@table @code
+@cindex babyl
+@cindex rmail mbox
+@item babyl
+The babyl (rmail) mail box.
+@cindex mbox
+@cindex Unix mbox
+@item mbox
+The standard Unix mbox file.
+@cindex MMDF mail box
+@item mmdf
+The MMDF mail box format.
+@item news
+Several news articles appended into a file.
+@item rnews
+@cindex rnews batch files
+The rnews batch transport format.
+@cindex forwarded messages
+@item forward
+Forwarded articles.
+@item mime-digest
+@cindex digest
+@cindex MIME digest
+@cindex 1153 digest
+@cindex RFC 1153 digest
+@cindex RFC 341 digest
+MIME (RFC 1341) digest format.
+@item standard-digest
+The standard (RFC 1153) digest format.
+@item slack-digest
+Non-standard digest format---matches most things, but does it badly. 
+@end table
+
+You can also use the special "file type" @code{guess}, which means that
+@code{nndoc} will try to guess what file type it is looking at.
+@code{digest} means that @code{nndoc} should guess what digest type the
+file is. 
 
 @code{nndoc} will not try to change the file or insert any extra headers into
 it---it will simply, like, let you use the file as the basis for a
@@ -2235,14 +2299,14 @@ You read articles and mail and answer and followup to the things you
 want.
 
 @item 
-You do the @kbd{G S r} command to pack these replies into a @sc{soup}
+You do the @kbd{G s r} command to pack these replies into a @sc{soup}
 packet.
 
 @item 
 You transfer this packet to the server.  
 
 @item
-You use Gnus to mail this packet out with the @kbd{G S s} command.
+You use Gnus to mail this packet out with the @kbd{G s s} command.
 
 @item
 You then repeat until you die.
@@ -2407,7 +2471,7 @@ Regular expression matching incoming @sc{soup} packets.  The default is
 
 
 @node SOUP Replies
-@subsubsection SOUP Replies
+@subsubsection @sc{SOUP} Replies
 
 Just using @code{nnsoup} won't mean that your postings and mailings end
 up in @sc{soup} reply packets automagically.  You have to work a bit
@@ -2993,11 +3057,11 @@ If non-@code{nil}, @code{nnmh} will read incoming mail.
 @item nnmh-be-safe
 @vindex nnmh-be-safe
 If non-@code{nil}, @code{nnmh} will go to ridiculous lengths to make
-sure that the articles in the folder is actually what Gnus think they
-are.  It will check date stamps, and stat everything in sight, so
+sure that the articles in the folder are actually what Gnus thinks they
+are.  It will check date stamps and stat everything in sight, so
 setting this to @code{t} will mean a serious slow-down.  If you never
-use anything by Gnus to read the @code{nnmh} articles, you do not have to set
-this variable to @code{t}. 
+use anything but Gnus to read the @code{nnmh} articles, you do not have
+to set this variable to @code{t}.
 @end table
 
 @node nnfolder
@@ -3372,8 +3436,8 @@ Go to the next group (@code{gnus-group-next-group}).
 @findex gnus-group-prev-group
 Go to the previous group (@code{gnus-group-prev-group}).
 
-@item SPC
-@kindex SPC (Browse)
+@item SPACE
+@kindex SPACE (Browse)
 @findex gnus-browse-read-group
 Enter the current group and display the first article
 (@code{gnus-browse-read-group}). 
@@ -3477,10 +3541,6 @@ the hook for the group mode:
 (add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
 @end lisp
 
-There are, in general, two methods for dividing the groups into topics.
-You can either sniff around some variables, or you can use some handy
-commands. 
-
 @menu 
 * Topic Variables::    How to customize the topics the Lisp Way.
 * Topic Commands::     Interactive E-Z commands.
@@ -3492,22 +3552,6 @@ commands.
 @subsection Topic Variables
 @cindex topic variables
 
-@vindex gnus-group-topics
-
-@code{gnus-group-topics} is the main variable that specifies what topics
-each group belong to.  That is an alist where each entry looks like
-this:
-
-@lisp
-(TOPIC REGEXP SHOW)
-@end lisp
-
-As you've already guessed (only geniï read manuals anyway), all
-groups that match @var{regexp} gets put into a section called
-@var{topic}.  If @var{show} is non-@code{nil}, it overrides
-@code{gnus-group-topic-topics-only}.  In specific, if @var{show} is
-@code{t}, all groups with this topic are always shown, and if it is a
-number, these groups are never shown.
 
 @vindex gnus-group-topic-topics-only
 Whoo, this is complicated.  If @code{gnus-group-topic-topics-only} is
@@ -3522,21 +3566,9 @@ If @code{gnus-topic-unique} is non-@code{nil}, each group will be member
 of (tops) one topic each.  If this is @code{nil}, each group might end
 up being a member of several topics.
 
-You can also put a @code{topic} in the group parameters (@pxref{Group
-Parameters}). 
-
 Now, if you select a topic, if will fold/unfold that topic, which is
 really neat, I think.
 
-Here's an example @code{gnus-group-topics}:
-
-@lisp
-(("Emacs - the Spice of Life" "^gnu.emacs\\|comp.emacs" t)
- ("Alternativeness" "^alt" 0)
- ("Hard Stuff" "^comp" nil)
- ("The Rest" "." nil))
-@end lisp
-
 @vindex gnus-topic-line-format
 The topic lines themselves are created according to the
 @code{gnus-topic-line-format} variable.  @xref{Formatting Variables}.
@@ -3703,6 +3735,11 @@ backend(s).
 Check whether new articles have arrived in the current group
 (@code{gnus-group-get-new-news-this-group}).
 
+@findex gnus-activate-all-groups
+@item C-c M-g
+@kindex C-c M-g (Group)
+Activate absolutely all groups (@code{gnus-activate-all-groups}). 
+
 @item ^
 @kindex ^ (Group)
 @findex gnus-group-enter-server-mode
@@ -3807,6 +3844,7 @@ move around, read articles, post articles and reply to articles.
 * Threading::                   How threads are made.
 * Asynchronous Fetching::       Gnus might be able to pre-fetch articles.
 * Article Caching::             You may store articles in a cache.
+* Persistent Articles::         Making articles expiry-resistant.
 * Article Backlog::             Having already read articles hang around.
 * Exiting the Summary Buffer::  Returning to the Group buffer.
 * Process/Prefix::              A convention used by many treatment commands.
@@ -5235,22 +5273,37 @@ can be deleted by Gnus at any time.  Expirable articles are marked with
 There are some marks that have nothing to do with whether the article is
 read or not.
 
+@itemize @bullet
+
+@item 
 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
+long thesis on cats' urinary tracts, and have to go home for dinner
 before you've finished reading the thesis.  You can then set a bookmark
 in the article, and Gnus will jump to this bookmark the next time it
 encounters the article.
 
+@item
 All articles that you have replied to or made a followup to (i.e., have
 answered) will be marked with an @samp{A} in the second column
 (@code{gnus-replied-mark}).
 
+@item 
+Articles that are stored in the article cache will be marked with an
+@samp{*} in the second column (@code{gnus-cached-mark}).
+
+@item 
+Articles that are "saved" (in some manner or other; not necessarily
+religously) are marked with an @samp{S} in the second column
+(@code{gnus-saved-mark}.  
+
+@item 
 @vindex gnus-not-empty-thread-mark
 @vindex gnus-empty-thread-mark
 It the @samp{%e} spec is used, the presence of threads or not will be
 marked with @code{gnus-not-empty-thread-mark} and
-@code{gnus-empty-thread-mark}, respectively.
+@code{gnus-empty-thread-mark} in the third column, respectively.
 
+@item 
 @vindex gnus-process-mark
 Finally we have the @dfn{process mark} (@code{gnus-process-mark}.  A
 variety of commands react to the presence of the process mark.  For
@@ -5258,6 +5311,17 @@ 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.
 
+@end itemize
+
+You might have noticed that most of these "non-readedness" marks appear
+in the second column by default.  So if you have a cached, saved,
+replied article that you have process-marked, what will that look like?
+
+Nothing much.  The presedence rules go as follows: process -> cache ->
+replied -> saved.  So if the article is in the cache and is replied,
+you'll only see the cache mark and not the replied mark.
+
+
 @node Setting Marks
 @subsection Setting Marks
 @cindex setting marks
@@ -5871,6 +5935,58 @@ you could set the @code{gnus-uncacheable-groups} regexp to
 default, since caching doesn't really work in @code{nnvirtual} groups,
 since @code{nnvirtual} assigns random article numbers to its articles.
 
+@findex gnus-cache-generate-nov-databases
+@findex gnus-cache-generate-active
+If your cache becomes all messed up for some reason or other,  Gnus
+offers two functions that will try to set things right.  @kbd{M-x
+gnus-cache-generate-nov-databases} will (re)build all the @sc{nov}
+files, and @kbd{gnus-cache-generate-active} will (re)generate the active
+file. 
+
+
+@node Persistent Articles
+@section Persistent Articles
+@cindex persistent articles
+
+Closely related to article caching, we have @dfn{persistent articles}.
+In fact, it's just a different way of looking at caching, and much more
+useful in my opinion.
+
+Say you're reading a newsgroup, and you happen on to some valuable gem
+that you want to keep and treasure forever.  You'd normally just save it
+(using one of the many saving commands) in some file.  The problem with
+that is that it's just, well, yucky.  Ideally you'd prefer just having
+the article remain in the group where you found it forever; untouched by
+the expiry going on at the news server.
+
+This is what a @dfn{persistent article} is---an article that just won't
+be deleted.  It's implemented using the normal cache functions, but
+you use two explicit commands for managing persistent articles:
+
+@table @kbd
+@item *
+@kindex * (Summary)
+@findex gnus-cache-enter-article
+Make the current article persistent (@code{gnus-cache-enter-article}). 
+
+@item M-*
+@kindex M-* (Summary)
+@findex gnus-cache-remove-article
+Remove the current article from the persistent articles
+(@code{gnus-cache-remove-article}).  This will normally delete the
+article. 
+@end table
+
+Both these commands understand the process/prefix convention. 
+
+To avoid having all ticked articles (and stuff) entered into the cache,
+you should set @code{gnus-use-cache} to @code{passive} if you're just
+interested in persistent articles:
+
+@lisp
+(setq gnus-use-cache 'passive)
+@end lisp
+
 
 @node Article Backlog
 @section Article Backlog
@@ -5972,6 +6088,21 @@ Exit the group and go to the previous group
 @code{gnus-exit-group-hook} is called when you exit the current
 group.  
 
+@findex gnus-summary-wake-up-the-dead
+@findex gnus-dead-summary-mode
+@vindex gnus-kill-summary-on-exit
+If you're in the habit of exiting groups, and then changing your mind
+about it, you might set @code{gnus-kill-summary-on-exit} to @code{nil}.
+If you do that, Gnus won't kill the summary buffer when you exit it.
+(Quelle surprise!)  Instead it will change the name of the buffer to
+something like @samp{"*Dead Summary ... *"} and install a minor mode
+called @code{gnus-dead-summary-mode}.  Now, if you switch back to this
+buffer, you'll find that all keys are mapped to a function called
+@code{gnus-summary-wake-up-the-dead}.  So tapping any keys in a dead
+summary buffer will result in a live, normal summary buffer.  
+
+There will never be more than one dead summary buffer at any one time. 
+
 @vindex gnus-use-cross-reference
 The data on the current group will be updated (which articles you have
 read, which articles you have replied to, etc.) when you exit the
@@ -6217,7 +6348,18 @@ a string (in which case it is used as a regexp to match on the article
 head); it can be a symbol (which will be called as a function); or it
 can be a list (which will be @code{eval}ed).  If any of these actions
 have a non-@code{nil} result, the @dfn{file} will be used as a default
-prompt. 
+prompt.  In addition, the result of the operation itself will be used if
+the function or form called returns a string or a list of strings. 
+
+You basically end up with a list of file names that might be used when
+saving the current article.  (All "matches" will be used.)  You will
+then be prompted for what you really want to use as a name, with file
+name completion over the results from applying this variable.
+
+This variable is @code{((gnus-article-archive-name))} by default, which
+means that Gnus will look at the articles it saves for an
+@samp{Archive-name} line and use that as a suggestion for the file
+name. 
 
 @vindex gnus-use-long-file-name
 Finally, you have the @code{gnus-use-long-file-name} variable.  If it is
@@ -6565,6 +6707,9 @@ pseudo-article will be created for each file to be viewed.  If
 @code{nil}, all files that use the same viewing command will be given as
 a list of parameters to that command.
 
+If @code{gnus-insert-pseudo-articles} is non-@code{nil}, insert
+pseudo-articles when decoding.  It is @code{t} by default.
+
 So; there you are, reading your @emph{pseudo-articles} in your
 @emph{virtual newsgroup} from the @emph{virtual server}; and you think:
 Why isn't anything real anymore? How did we get here?
@@ -7194,11 +7339,14 @@ the process mark (@code{gnus-summary-universal-argument}).
 @item A D
 @kindex A D (Summary)
 @findex gnus-summary-enter-digest-group
-If the current article is a digest, you might use this command to enter
-a group based on the current digest
-(@code{gnus-summary-enter-digest-group}).  Gnus will try to guess what
-article type is currently displayed unless you give a prefix to this
-command, which forces a "digest" interpretation.
+If the current article is a collection of other articles (for instance,
+a digest), you might use this command to enter a group based on the that
+article (@code{gnus-summary-enter-digest-group}).  Gnus will try to
+guess what article type is currently displayed unless you give a prefix
+to this command, which forces a "digest" interpretation.  Basically,
+whenever you see a message that is a collection of other messages on
+some format, you @kbd{A D} and read these messages in a more convenient
+fashion. 
 
 @item C-t
 @kindex C-t (Summary)
@@ -7262,6 +7410,9 @@ the article and the subject, you'd say:
 (setq gnus-visible-headers "^From:\\|^Subject:")
 @end lisp
 
+This variable can also be a list of regexps to match headers that are to
+remain visible.
+
 @item gnus-ignored-headers
 @vindex gnus-ignored-headers
 This variable is the reverse of @code{gnus-visible-headers}.  If this
@@ -7276,8 +7427,12 @@ and the @code{Xref} line, you might say:
 (setq gnus-ignored-headers "^References:\\|^Xref:")
 @end lisp
 
+This variable can also be a list of regexps to match headers that are to
+be removed.
+
 Note that if @code{gnus-visible-headers} is non-@code{nil}, this
 variable will have no effect.
+
 @end table
 
 @vindex gnus-sorted-header-list
@@ -7367,37 +7522,56 @@ make them invisible if you want to make them go away.
 A few additional keystrokes are available:
 
 @table @kbd
+
 @item SPACE
 @kindex SPACE (Article)
 @findex gnus-article-next-page
 Scroll forwards one page (@code{gnus-article-next-page}).
+
 @item DEL
 @kindex DEL (Article)
 @findex gnus-article-prev-page
 Scroll backwards one page (@code{gnus-article-prev-page}).
+
 @item C-c ^
 @kindex C-c ^ (Article)
 @findex gnus-article-refer-article
 If point is in the neighborhood of a @code{Message-ID} and you press
 @kbd{r}, Gnus will try to get that article from the server
 (@code{gnus-article-refer-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}).  If
 given a prefix, include the mail.
+
 @item s
 @kindex s (Article)
 @findex gnus-article-show-summary
 Reconfigure the buffers so that the summary buffer becomes visible
 (@code{gnus-article-show-summary}).
+
 @item ?
 @kindex ? (Article)
 @findex gnus-article-describe-briefly
 Give a very brief description of the available keystrokes
 (@code{gnus-article-describe-briefly}). 
+
+@item TAB
+@kindex TAB (Article)
+@findex gnus-article-next-button
+Go to the next button, if any (@code{gnus-article-next-button}.  This
+only makes sense if you have buttonizing turned on.
+
+@item M-TAB
+@kindex M-TAB (Article)
+@findex gnus-article-prev-button
+Go to the previous button, if any (@code{gnus-article-prev-button}.  
+
 @end table
 
+
 @node Misc Article
 @section Misc Article
 
@@ -8116,30 +8290,44 @@ some author.  Uses the same match types as the @code{From} header uses.
 @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 thread-mark-and-expunge
+The value of this entry should be a number.  All articles that belong to
+a thread that has a total score below this number will be marked as read
+and removed from the summary buffer.  @code{gnus-thread-score-function}
+says how to compute the total score for a thread.
+
 @item files
 The value of this entry should be any number of file names.  These files
 are assumed to be score files as well, and will be loaded the same way
 this one was.
+
 @item exclude-files
 The clue of this entry should be any number of files.  This files will
 not be loaded, even though they would normally be so, for some reason or
 other. 
+
 @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}).
+
 @item orphan
 The value of this entry should be a number.  Articles that do not have
 parents will get this number added to their scores.
+
 @item adapt
 This entry controls the adaptive scoring.  If it is @code{t}, the
 default adaptive scoring rules will be used.  If it is @code{ignore}, no
@@ -8153,6 +8341,13 @@ not want adaptive scoring.  If you only want adaptive scoring in a few
 groups, you'd set @code{gnus-use-adaptive-scoring} to @code{nil}, and
 insert @code{(adapt t)} in the score files of the groups where you want
 it. 
+
+@item adapt-file
+All adaptive score entries will go to the file named by this entry.  It
+will also be applied when entering the group.  This atom might be handy
+if you want to adapt on several groups at once, using the same adaptive
+file for a number of groups.
+
 @item local
 @cindex local variables
 The value of this entry should be a list of @code{(VAR VALUE)} pairs.
@@ -8912,6 +9107,7 @@ mode lines, and therefore have to be cut off at some point.  This
 variable says how long the other elements on the line is (i.e., the
 non-info part).  If you put additional elements on the mode line (eg. a
 clock), you should modify this variable:
+
 @c Hook written by Keinonen Kari <kk85613@cs.tut.fi>.
 @lisp
 (add-hook 'display-time-hook
@@ -8920,6 +9116,9 @@ clock), you should modify this variable:
                  (+ 21 (length display-time-string)))))
 @end lisp
 
+If this variable is @code{nil} (which is the default), the mode line
+strings won't be chopped off, and they won't be padded either.
+
 @item gnus-visual
 @vindex gnus-visual
 @cindex visual