*** empty log message ***
[gnus] / lisp / gnus.el
index 78b5dec..a4cc567 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus.el --- a newsreader for GNU Emacs
-;; Copyright (C) 1987,88,89,90,93,94,95 Free Software Foundation, Inc.
+;; Copyright (C) 1987,88,89,90,93,94,95,96 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 
 ;; 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
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
-;; Although Gnus looks suspiciously like GNUS, it isn't quite the same
-;; beast. Most internal structures have been changed. If you have
-;; written packages that depend on any of the hash tables,
-;; `gnus-newsrc-alist', `gnus-killed-assoc', marked lists, the .newsrc
-;; buffer, or internal knowledge of the `nntp-header-' macros, or
-;; dependence on the buffers having a certain format, your code will
-;; fail.
-
 ;;; Code:
 
+(eval '(run-hooks 'gnus-load-hook))
+
 (require 'mail-utils)
 (require 'timezone)
 (require 'nnheader)
+(require 'message)
 
-;; Site dependent variables. These variables should be defined in
+(eval-when-compile (require 'cl))
+
+;; Site dependent variables.  These variables should be defined in
 ;; paths.el.
 
 (defvar gnus-default-nntp-server nil
@@ -47,7 +45,7 @@ by the user.
 If you want to change servers, you should use `gnus-select-method'.
 See the documentation to that variable.")
 
-(defconst gnus-backup-default-subscribed-newsgroups 
+(defvar gnus-backup-default-subscribed-newsgroups
   '("news.announce.newusers" "news.groups.questions" "gnu.emacs.gnus")
   "Default default new newsgroups the first time Gnus is run.
 Should be set in paths.el, and shouldn't be touched by the user.")
@@ -62,35 +60,60 @@ no need to set this variable.")
   "String with a description of what organization (if any) the user belongs to.
 The ORGANIZATION environment variable is used instead if it is defined.
 If this variable contains a function, this function will be called
-with the current newsgroup name as the argument. The function should
+with the current newsgroup name as the argument.  The function should
 return a string.
 
 In any case, if the string (either in the variable, in the environment
 variable, or returned by the function) is a file name, the contents of
 this file will be used as the organization.")
 
-(defvar gnus-use-generic-from nil
-  "If nil, the full host name will be the system name prepended to the domain name.
-If this is a string, the full host name will be this string.
-If this is non-nil, non-string, the domain name will be used as the
-full host name.")
+;; Customization variables
 
-(defvar gnus-use-generic-path nil
-  "If nil, use the NNTP server name in the Path header.
-If stringp, use this; if non-nil, use no host name (user name only).")
+;; Don't touch this variable.
+(defvar gnus-nntp-service "nntp"
+  "*NNTP service name (\"nntp\" or 119).
+This is an obsolete variable, which is scarcely used.  If you use an
+nntp server for your newsgroup and want to change the port number
+used to 899, you would say something along these lines:
 
+ (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))")
 
-;; Customization variables
+(defvar gnus-nntpserver-file "/etc/nntpserver"
+  "*A file with only the name of the nntp server in it.")
 
-(defvar gnus-select-method 
-  (list 'nntp (or (getenv "NNTPSERVER") 
-                 (if (and gnus-default-nntp-server
-                          (not (string= gnus-default-nntp-server "")))
-                     gnus-default-nntp-server)
-                 (system-name)))
+;; This function is used to check both the environment variable
+;; NNTPSERVER and the /etc/nntpserver file to see whether one can find
+;; an nntp server name default.
+(defun gnus-getenv-nntpserver ()
+  (or (getenv "NNTPSERVER")
+      (and (file-readable-p gnus-nntpserver-file)
+          (save-excursion
+            (set-buffer (get-buffer-create " *gnus nntp*"))
+            (buffer-disable-undo (current-buffer))
+            (insert-file-contents gnus-nntpserver-file)
+            (let ((name (buffer-string)))
+              (prog1
+                  (if (string-match "^[ \t\n]*$" name)
+                      nil
+                    name)
+                (kill-buffer (current-buffer))))))))
+
+(defvar gnus-select-method
+  (nconc
+   (list 'nntp (or (condition-case ()
+                      (gnus-getenv-nntpserver)
+                    (error nil))
+                  (if (and gnus-default-nntp-server
+                           (not (string= gnus-default-nntp-server "")))
+                      gnus-default-nntp-server)
+                  (system-name)))
+   (if (or (null gnus-nntp-service)
+          (equal gnus-nntp-service "nntp"))
+       nil
+     (list gnus-nntp-service)))
   "*Default method for selecting a newsgroup.
 This variable should be a list, where the first element is how the
-news is to be fetched, the second is the address. 
+news is to be fetched, the second is the address.
 
 For instance, if you want to get your news via NNTP from
 \"flab.flab.edu\", you could say:
@@ -106,30 +129,27 @@ If you use this variable, you must set `gnus-nntp-server' to nil.
 There is a lot more to know about select methods and virtual servers -
 see the manual for details.")
 
-;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>.
-(defvar gnus-post-method nil
-  "*Preferred method for posting USENET news.
-If this variable is nil, Gnus will use the current method to decide
-which method to use when posting.  If it is non-nil, it will override
-the current method.  This method will not be used in mail groups and
-the like, only in \"real\" newsgroups.
-
-The value must be a valid method as discussed in the documentation of
-`gnus-select-method'.")
+(defvar gnus-message-archive-method 
+  '(nnfolder "archive" (nnfolder-directory "~/Mail/archive/")
+            (nnfolder-active-file "~/Mail/archive/active")
+            (nnfolder-get-new-mail nil)
+            (nnfolder-inhibit-expiry t))
+  "*Method used for archiving messages you've sent.
+This should be a mail method.")
 
 (defvar gnus-refer-article-method nil
   "*Preferred method for fetching an article by Message-ID.
 If you are reading news from the local spool (with nnspool), fetching
-articles by Message-ID is painfully slow. By setting this method to an
+articles by Message-ID is painfully slow.  By setting this method to an
 nntp method, you might get acceptable results.
 
 The value of this variable must be a valid select method as discussed
-in the documentation of `gnus-select-method'")
+in the documentation of `gnus-select-method'.")
 
 (defvar gnus-secondary-select-methods nil
   "*A list of secondary methods that will be used for reading news.
 This is a list where each element is a complete select method (see
-`gnus-select-method').  
+`gnus-select-method').
 
 If, for instance, you want to read your mail with the nnml backend,
 you could set this variable:
@@ -143,17 +163,9 @@ non-numeric prefix - `C-u M-x gnus', in short.")
 
 (defvar gnus-nntp-server nil
   "*The name of the host running the NNTP server.
-This variable is semi-obsolete. Use the `gnus-select-method'
+This variable is semi-obsolete.         Use the `gnus-select-method'
 variable instead.")
 
-(defvar gnus-nntp-service "nntp"
-  "*NNTP service name (\"nntp\" or 119).
-This is an obsolete variable, which is scarcely used. If you use an
-nntp server for your newsgroup and want to change the port number
-used to 899, you would say something along these lines:
-
- (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))")
-
 (defvar gnus-startup-file "~/.newsrc"
   "*Your `.newsrc' file.
 `.newsrc-SERVER' will be used instead if that exists.")
@@ -161,33 +173,46 @@ used to 899, you would say something along these lines:
 (defvar gnus-init-file "~/.gnus"
   "*Your Gnus elisp startup file.
 If a file with the .el or .elc suffixes exist, it will be read
-instead.") 
+instead.")
 
 (defvar gnus-group-faq-directory
-  "/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
+  '("/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
+    "/ftp@sunsite.auc.dk:/pub/usenet/"
+    "/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
+    "/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
+    "/ftp@rtfm.mit.edu:/pub/usenet/"
+    "/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
+    "/ftp@ftp.sunet.se:/pub/usenet/"
+    "/ftp@nctuccca.edu.tw:/USENET/FAQ/"
+    "/ftp@hwarang.postech.ac.kr:/pub/usenet/"
+    "/ftp@ftp.hk.super.net:/mirror/faqs/")
   "*Directory where the group FAQs are stored.
 This will most commonly be on a remote machine, and the file will be
 fetched by ange-ftp.
 
+This variable can also be a list of directories.  In that case, the
+first element in the list will be used by default, and the others will
+be used as backup sites.
+
 Note that Gnus uses an aol machine as the default directory.  If this
 feels fundamentally unclean, just think of it as a way to finally get
 something of value back from them.
 
 If the default site is too slow, try one of these:
 
-   North America: ftp.uu.net                     /usenet/news.answers
-                 mirrors.aol.com                /pub/rtfm/usenet
-                 ftp.seas.gwu.edu               /pub/rtfm
-                  rtfm.mit.edu                   /pub/usenet/news.answers
-   Europe:        ftp.uni-paderborn.de           /pub/FAQ
-                 ftp.Germany.EU.net             /pub/newsarchive/news.answers
-                 ftp.sunet.se                   /pub/usenet
-   Asia:          nctuccca.edu.tw                /USENET/FAQ
-                 hwarang.postech.ac.kr          /pub/usenet/news.answers
-                 ftp.hk.super.net               /mirror/faqs")
+   North America: mirrors.aol.com               /pub/rtfm/usenet
+                 ftp.seas.gwu.edu               /pub/rtfm
+                 rtfm.mit.edu                   /pub/usenet
+   Europe:       ftp.uni-paderborn.de           /pub/FAQ
+                  src.doc.ic.ac.uk               /usenet/news-FAQS
+                 ftp.sunet.se                   /pub/usenet
+                 sunsite.auc.dk                 /pub/usenet
+   Asia:         nctuccca.edu.tw                /USENET/FAQ
+                 hwarang.postech.ac.kr          /pub/usenet
+                 ftp.hk.super.net               /mirror/faqs")
 
 (defvar gnus-group-archive-directory
-  "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/" 
+  "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
   "*The address of the (ding) archives.")
 
 (defvar gnus-group-recent-archive-directory
@@ -203,74 +228,30 @@ started; it'll just use the normal newsgroups subscription methods.")
 (defvar gnus-use-cross-reference t
   "*Non-nil means that cross referenced articles will be marked as read.
 If nil, ignore cross references.  If t, mark articles as read in
-subscribed newsgroups. If neither t nor nil, mark as read in all
-newsgroups.") 
+subscribed newsgroups. If neither t nor nil, mark as read in all
+newsgroups.")
+
+(defvar gnus-single-article-buffer t
+  "*If non-nil, display all articles in the same buffer.
+If nil, each group will get its own article buffer.")
 
 (defvar gnus-use-dribble-file t
   "*Non-nil means that Gnus will use a dribble file to store user updates.
 If Emacs should crash without saving the .newsrc files, complete
 information can be restored from the dribble file.")
 
+(defvar gnus-dribble-directory nil
+  "*The directory where dribble files will be saved.
+If this variable is nil, the directory where the .newsrc files are
+saved will be used.")
+
 (defvar gnus-asynchronous nil
   "*If non-nil, Gnus will supply backends with data needed for async article fetching.")
 
-(defvar gnus-asynchronous-article-function nil
-  "*Function for picking articles to pre-fetch, possibly.")
-
-(defvar gnus-score-file-single-match-alist nil
-  "*Alist mapping regexps to lists of score files.
-Each element of this alist should be of the form
-       (\"REGEXP\" [ \"SCORE-FILE-1\" ] [ \"SCORE-FILE-2\" ] ... )
-
-If the name of a group is matched by REGEXP, the corresponding scorefiles
-will be used for that group.
-The first match found is used, subsequent matching entries are ignored (to
-use multiple matches, see gnus-score-file-multiple-match-alist).
-
-These score files are loaded in addition to any files returned by
-gnus-score-find-score-files-function (which see).")
-
-(defvar gnus-score-file-multiple-match-alist nil
-  "*Alist mapping regexps to lists of score files.
-Each element of this alist should be of the form
-       (\"REGEXP\" [ \"SCORE-FILE-1\" ] [ \"SCORE-FILE-2\" ] ... )
-
-If the name of a group is matched by REGEXP, the corresponding scorefiles
-will be used for that group.
-If multiple REGEXPs match a group, the score files corresponding to each
-match will be used (for only one match to be used, see
-gnus-score-file-single-match-alist).
-
-These score files are loaded in addition to any files returned by
-gnus-score-find-score-files-function (which see).")
-
-
-(defvar gnus-score-file-suffix "SCORE"
-  "*Suffix of the score files.")
-
-(defvar gnus-adaptive-file-suffix "ADAPT"
-  "*Suffix of the adaptive score files.")
-
-(defvar gnus-score-find-score-files-function 'gnus-score-find-bnews
-  "*Function used to find score files.
-The function will be called with the group name as the argument, and
-should return a list of score files to apply to that group.  The score
-files do not actually have to exist.
-
-Predefined values are:
-
-gnus-score-find-single: Only apply the group's own score file.
-gnus-score-find-hierarchical: Also apply score files from parent groups.
-gnus-score-find-bnews: Apply score files whose names matches.
-
-See the documentation to these functions for more information.
-
-This variable can also be a list of functions to be called.  Each
-function should either return a list of score files, or a list of
-score alists.")
-
-(defvar gnus-score-interactive-default-score 1000
-  "*Scoring commands will raise/lower the score with this number as the default.")
+(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.
@@ -312,6 +293,15 @@ Gnus provides the following functions:
 * gnus-summary-save-in-file (article format).
 * gnus-summary-save-in-vm (use VM's folder format).")
 
+(defvar gnus-prompt-before-saving 'always
+  "*This variable says how much prompting is to be done when saving articles.
+If it is nil, no prompting will be done, and the articles will be
+saved to the default files.  If this variable is `always', each and
+every article that is saved will be preceded by a prompt, even when
+saving large batches of articles.  If this variable is neither nil not
+`always', there the user will be prompted once for a file name for
+each invocation of the saving commands.")
+
 (defvar gnus-rmail-save-name (function gnus-plain-save-name)
   "*A function generating a file name to save articles in Rmail format.
 The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
@@ -329,16 +319,31 @@ 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-move-split-methods nil
+  "*Variable used to suggest where articles are to be moved to.
+It uses the same syntax as the `gnus-split-methods' variable.")
 
 (defvar gnus-save-score nil
   "*If non-nil, save group scoring info.")
@@ -347,21 +352,47 @@ 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-use-trees nil
+  "*If non-nil, display a thread tree buffer.")
+
+(defvar gnus-use-grouplens nil
+  "*If non-nil, use GroupLens ratings.")
+
+(defvar gnus-keep-backlog nil
+  "*If non-nil, Gnus will keep read articles for later re-retrieval.
+If it is a number N, then Gnus will only keep the last N articles
+read.  If it is neither nil nor a number, Gnus will keep all read
+articles.  This is not a good idea.")
+
+(defvar gnus-use-nocem nil
+  "*If non-nil, Gnus will read NoCeM cancel messages.")
+
+(defvar gnus-use-demon nil
+  "If non-nil, Gnus might use some demons.")
 
 (defvar gnus-use-scoring t
   "*If non-nil, enable scoring.")
 
+(defvar gnus-use-picons nil
+  "*If non-nil, display picons.")
+
 (defvar gnus-fetch-old-headers nil
   "*Non-nil means that Gnus will try to build threads by grabbing old headers.
 If an unread article in the group refers to an older, already read (or
 just marked as read) article, the old article will not normally be
 displayed in the Summary buffer.  If this variable is non-nil, Gnus
 will attempt to grab the headers to the old articles, and thereby
-build complete threads.  If it has the value `some', only enough
+build complete threads.         If it has the value `some', only enough
 headers to connect otherwise loose threads will be displayed.
+This variable can also be a number.  In that case, no more than that
+number of old headers will be fetched.
 
-The server has to support XOVER for any of this to work.")
+The server has to support NOV for any of this to work.")
 
 ;see gnus-cus.el
 ;(defvar gnus-visual t
@@ -389,9 +420,9 @@ jabbering all the time.")
 (defvar gnus-keep-same-level nil
   "*Non-nil means that the next newsgroup after the current will be on the same level.
 When you type, for instance, `n' after reading the last article in the
-current newsgroup, you will go to the next newsgroup. If this variable
+current newsgroup, you will go to the next newsgroup.  If this variable
 is nil, the next newsgroup will be the next from the group
-buffer. 
+buffer.
 If this variable is non-nil, Gnus will either put you in the
 next newsgroup with the same level, or, if no such newsgroup is
 available, the next newsgroup with the lowest possible level higher
@@ -403,8 +434,8 @@ with the best level.")
   "*nil means that Gnus won't gather loose threads.
 If the root of a thread has expired or been read in a previous
 session, the information necessary to build a complete thread has been
-lost. Instead of having many small sub-threads from this original thread
-scattered all over the summary buffer, Gnus can gather them. 
+lost.  Instead of having many small sub-threads from this original thread
+scattered all over the summary buffer, Gnus can gather them.
 
 If non-nil, Gnus will try to gather all loose sub-threads from an
 original thread into one large thread.
@@ -419,9 +450,15 @@ have all the sub-threads as children.
 If this variable is `adopt', Gnus will make one of the \"children\"
 the parent and mark all the step-children as such.
 If this variable is `empty', the \"children\" are printed with empty
-subject fields.  (Or rather, they will be printed with a string
+subject fields.         (Or rather, they will be printed with a string
 given by the `gnus-summary-same-subject' variable.)")
 
+(defvar gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
+  "*A regexp to match subjects to be excluded from loose thread gathering.
+As loose thread gathering is done on subjects only, that means that
+there can be many false gatherings performed.  By rooting out certain
+common subjects, gathering might become saner.")
+
 (defvar gnus-summary-gather-subject-limit nil
   "*Maximum length of subject comparisons when gathering loose threads.
 Use nil to compare full subjects.  Setting this variable to a low
@@ -433,6 +470,22 @@ same few characters will be incorrectly gathered.
 If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
 comparing subjects.")
 
+(defvar gnus-simplify-ignored-prefixes nil
+  "*Regexp, matches for which are removed from subject lines when simplifying.")
+
+(defvar gnus-build-sparse-threads nil
+  "*If non-nil, fill in the gaps in threads.
+If `some', only fill in the gaps that are needed to tie loose threads
+together.  If `more', fill in all leaf nodes that Gnus can find.  If
+non-nil and non-`some', fill in all gaps that Gnus manages to guess.")
+
+(defvar gnus-summary-thread-gathering-function 'gnus-gather-threads-by-subject
+  "Function used for gathering loose threads.
+There are two pre-defined functions: `gnus-gather-threads-by-subject',
+which only takes Subjects into consideration; and
+`gnus-gather-threads-by-references', which compared the References
+headers of the articles to find matches.")
+
 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defvar gnus-summary-same-subject ""
   "*String indicating that the current article has the same subject as the previous.
@@ -440,25 +493,30 @@ This variable will only be used if the value of
 `gnus-summary-make-false-root' is `empty'.")
 
 (defvar gnus-summary-goto-unread t
-  "*If non-nil, marking commands will go to the next unread article.")
+  "*If non-nil, marking commands will go to the next unread article.
+If `never', \\<gnus-summary-mode-map>\\[gnus-summary-next-page] will go to the next article,
+whether it is read or not.")
 
 (defvar gnus-group-goto-unread t
   "*If non-nil, movement commands will go to the next unread and subscribed group.")
 
+(defvar gnus-goto-next-group-when-activating t
+  "*If non-nil, the \\<gnus-group-mode-map>\\[gnus-group-get-new-news-this-group] command will advance point to the next group.")
+
 (defvar gnus-check-new-newsgroups t
   "*Non-nil means that Gnus will add new newsgroups at startup.
 If this variable is `ask-server', Gnus will ask the server for new
-groups since the last time it checked. This means that the killed list
+groups since the last time it checked. This means that the killed list
 is no longer necessary, so you could set `gnus-save-killed-list' to
-nil. 
+nil.
 
-A variant is to have this variable be a list of select methods. Gnus
+A variant is to have this variable be a list of select methods.         Gnus
 will then use the `ask-server' method on all these select methods to
 query for new groups from all those servers.
 
 Eg.
-  (setq gnus-check-new-newsgroups 
-        '((nntp \"some.server\") (nntp \"other.server\")))
+  (setq gnus-check-new-newsgroups
+       '((nntp \"some.server\") (nntp \"other.server\")))
 
 If this variable is nil, then you have to tell Gnus explicitly to
 check for new newsgroups with \\<gnus-group-mode-map>\\[gnus-find-new-newsgroups].")
@@ -503,16 +561,21 @@ 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
+If it is non-nil, it should be a number between one and nine.  Foreign
 newsgroups that have a level lower or equal to this number will be
-activated on startup. For instance, if you want to active all
-subscribed newsgroups, but not the rest, you'd set this variable to 
+activated on startup.  For instance, if you want to active all
+subscribed newsgroups, but not the rest, you'd set this variable to
 `gnus-level-subscribed'.
 
 If you subscribe to lots of newsgroups from different servers, startup
-might take a while. By setting this variable to nil, you'll save time,
+might take a while.  By setting this variable to nil, you'll save time,
 but you won't be told how many unread articles there are in the
 groups.")
 
@@ -526,12 +589,13 @@ exit.")
 
 (defvar gnus-save-killed-list t
   "*If non-nil, save the list of killed groups to the startup file.
-This will save both time (when starting and quitting) and space (both
-memory and disk), but it will also mean that Gnus has no record of
-which groups are new and which are old, so the automatic new
-newsgroups subscription methods become meaningless. You should always
-set `gnus-check-new-newsgroups' to `ask-server' or nil if you set this
-variable to nil.")
+If you set this variable to nil, you'll save both time (when starting
+and quitting) and space (both memory and disk), but it will also mean
+that Gnus has no record of which groups are new and which are old, so
+the automatic new newsgroups subscription methods become meaningless.
+
+You should always set `gnus-check-new-newsgroups' to `ask-server' or
+nil if you set this variable to nil.")
 
 (defvar gnus-interactive-catchup t
   "*If non-nil, require your confirmation when catching up a group.")
@@ -565,28 +629,46 @@ Articles with scores closer than this to `gnus-summary-default-score'
 will not be marked.")
 
 (defvar gnus-simplify-subject-fuzzy-regexp nil
-  "*Regular expression that will be removed from subject strings if
-fuzzy subject simplification is selected.")
+  "*Strings to be removed when doing fuzzy matches.
+This can either be a regular expression or list of regular expressions
+that will be removed from subject strings if fuzzy subject
+simplification is selected.")
+
+(defvar gnus-permanently-visible-groups nil
+  "*Regexp to match groups that should always be listed in the group buffer.
+This means that they will still be listed when there are no unread
+articles in the groups.")
+
+(defvar gnus-list-groups-with-ticked-articles t
+  "*If non-nil, list groups that have only ticked articles.
+If nil, only list groups that have unread articles.")
 
 (defvar gnus-group-default-list-level gnus-level-subscribed
-  "*Default listing level. 
+  "*Default listing level.
 Ignored if `gnus-group-use-permanent-levels' is non-nil.")
 
 (defvar gnus-group-use-permanent-levels nil
   "*If non-nil, once you set a level, Gnus will use this level.")
 
+(defvar gnus-group-list-inactive-groups t
+  "*If non-nil, inactive groups will be listed.")
+
 (defvar gnus-show-mime nil
   "*If non-nil, do mime processing of articles.
 The articles will simply be fed to the function given by
 `gnus-show-mime-method'.")
 
 (defvar gnus-strict-mime t
-  "*If nil, decode MIME header even if there is not Mime-Version field.")
-(defvar gnus-show-mime-method (function metamail-buffer)
+  "*If nil, MIME-decode even if there is no Mime-Version header in the article.")
+
+(defvar gnus-show-mime-method 'metamail-buffer
   "*Function to process a MIME message.
 The function is called from the article buffer.")
 
+(defvar gnus-decode-encoded-word-method (lambda ())
+  "*Function to decode a MIME encoded-words.
+The function is called from the article buffer.")
+
 (defvar gnus-show-threads t
   "*If non-nil, display threads in summary mode.")
 
@@ -604,16 +686,26 @@ to expose hidden threads.")
 If nil, which is the default, articles that have different subjects
 from their parents will start separate threads.")
 
+(defvar gnus-thread-operation-ignore-subject t
+  "*If non-nil, subjects will be ignored when doing thread commands.
+This affects commands like `gnus-summary-kill-thread' and
+`gnus-summary-lower-thread'.
+
+If this variable is nil, articles in the same thread with different
+subjects will not be included in the operation in question.  If this
+variable is `fuzzy', only articles that have subjects that are fuzzily
+equal will be included.")
+
 (defvar gnus-thread-indent-level 4
   "*Number that says how much each sub-thread should be indented.")
 
-(defvar gnus-ignored-newsgroups 
+(defvar gnus-ignored-newsgroups
   (purecopy (mapconcat 'identity
-                       '("^to\\."       ; not "real" groups
-                         "^[0-9. \t]+ " ; all digits in name
-                         "[][\"#'()]"   ; bogus characters
-                         )
-                       "\\|"))
+                      '("^to\\."       ; not "real" groups
+                        "^[0-9. \t]+ " ; all digits in name
+                        "[][\"#'()]"   ; bogus characters
+                        )
+                      "\\|"))
   "*A regexp to match uninteresting newsgroups in the active file.
 Any lines in the active file matching this regular expression are
 removed from the newsgroup list before anything else is done to it,
@@ -622,48 +714,78 @@ 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:"
+(defvar gnus-visible-headers "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-"
   "*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
-  '("^From:" "^Subject:" "^Summary:" "^Keywords:" "^Newsgroups:" "^To:" 
+  '("^From:" "^Subject:" "^Summary:" "^Keywords:" "^Newsgroups:" "^To:"
     "^Cc:" "^Date:" "^Organization:")
   "*This variable is a list of regular expressions.
 If it is non-nil, headers that match the regular expressions will
 be placed first in the article buffer in the sequence specified by
 this list.")
 
+(defvar gnus-boring-article-headers
+  '(empty followup-to reply-to)
+  "*Headers that are only to be displayed if they have interesting data.
+Possible values in this list are `empty', `newsgroups', `followup-to',
+`reply-to', and `date'.")
+
 (defvar gnus-show-all-headers nil
   "*If non-nil, don't hide any headers.")
 
 (defvar gnus-save-all-headers t
   "*If non-nil, don't remove any headers before saving.")
 
+(defvar gnus-saved-headers gnus-visible-headers
+  "*Headers to keep if `gnus-save-all-headers' is nil.
+If `gnus-save-all-headers' is non-nil, this variable will be ignored.
+If that variable is nil, however, all headers that match this regexp
+will be kept while the rest will be deleted before saving.")
+
 (defvar gnus-inhibit-startup-message nil
   "*If non-nil, the startup message will not be displayed.")
 
 (defvar gnus-signature-separator "^-- *$"
   "Regexp matching signature separator.")
 
+(defvar gnus-signature-limit nil
+  "Provide a limit to what is considered a signature.
+If it is a number, no signature may not be longer (in characters) than
+that number.  If it is a function, the function will be called without
+any parameters, and if it returns nil, there is no signature in the
+buffer.  If it is a string, it will be used as a regexp.  If it
+matches, the text in question is not a signature.")
+
 (defvar gnus-auto-extend-newsgroup t
   "*If non-nil, extend newsgroup forward and backward when requested.")
 
 (defvar gnus-auto-select-first t
-  "*If non-nil, select the first unread article when entering a group.
+  "*If nil, don't select the first unread article when entering a group.
+If this variable is `best', select the highest-scored unread article
+in the group.  If neither nil nor `best', select the first unread
+article.
+
 If you want to prevent automatic selection of the first unread article
 in some newsgroups, set the variable to nil in
-`gnus-select-group-hook'.") 
+`gnus-select-group-hook'.")
 
 (defvar gnus-auto-select-next t
   "*If non-nil, offer to go to the next group from the end of the previous.
 If the value is t and the next newsgroup is empty, Gnus will exit
-summary mode and go back to group mode.  If the value is neither nil
-nor t, Gnus will select the following unread newsgroup.  In
+summary mode and go back to group mode.         If the value is neither nil
+nor t, Gnus will select the following unread newsgroup.         In
 particular, if the value is the symbol `quietly', the next unread
-newsgroup will be selected without any confirmations.")
+newsgroup will be selected without any confirmation, and if it is
+`almost-quietly', the next group will be selected without any
+confirmation if you are located on the last article in the group.
+Finally, if this variable is `slightly-quietly', the `Z n' command
+will go to the next group without confirmation.")
 
 (defvar gnus-auto-select-same nil
   "*If non-nil, select the next article with the same subject.")
@@ -674,7 +796,9 @@ The \"unread\" movement commands will stay on the same line if the
 current article is unread.")
 
 (defvar gnus-auto-center-summary t
-  "*If non-nil, always center the current summary buffer.")
+  "*If non-nil, always center the current summary buffer.
+In particular, if `vertical' do only vertical recentering.  If non-nil
+and non-`vertical', do both horizontal and vertical recentering.")
 
 (defvar gnus-break-pages t
   "*If non-nil, do page breaking on articles.
@@ -692,49 +816,119 @@ beginning of a line.")
 (defvar gnus-window-configuration nil
   "Obsolete variable.  See `gnus-buffer-configuration'.")
 
+(defvar gnus-window-min-width 2
+  "*Minimum width of Gnus buffers.")
+
+(defvar gnus-window-min-height 1
+  "*Minimum height of Gnus buffers.")
+
 (defvar gnus-buffer-configuration
-  '((group ([group 1.0 point] 
-           (if gnus-carpal [group-carpal 4])))
-    (summary ([summary 1.0 point]
-             (if gnus-carpal [summary-carpal 4])))
-    (article ([summary 0.25 point] 
-             (if gnus-carpal [summary-carpal 4]) 
-             [article 1.0]))
-    (server ([server 1.0 point]
-            (if gnus-carpal [server-carpal 2])))
-    (browse ([browse 1.0 point]
-            (if gnus-carpal [browse-carpal 2])))
-    (group-mail ([mail 1.0 point]))
-    (summary-mail ([mail 1.0 point]))
-    (summary-reply ([article 0.5]
-                   [mail 1.0 point]))
-    (info ([nil 1.0 point]))
-    (summary-faq ([summary 0.25]
-                 [faq 1.0 point]))
-    (edit-group ([group 0.5]
-                [edit-group 1.0 point]))
-    (edit-server ([server 0.5]
-                 [edit-server 1.0 point]))
-    (edit-score ([summary 0.25]
-                [edit-score 1.0 point]))
-    (post ([post 1.0 point]))
-    (reply ([article 0.5]
-           [mail 1.0 point]))
-    (mail-forward ([mail 1.0 point]))
-    (post-forward ([post 1.0 point]))
-    (reply-yank ([mail 1.0 point]))
-    (followup ([article 0.5]
-              [post 1.0 point]))
-    (followup-yank ([post 1.0 point])))
+  '((group
+     (vertical 1.0
+              (group 1.0 point)
+              (if gnus-carpal '(group-carpal 4))))
+    (summary
+     (vertical 1.0
+              (summary 1.0 point)
+              (if gnus-carpal '(summary-carpal 4))))
+    (article
+     (cond 
+      (gnus-use-picons
+       '(frame 1.0
+              (vertical 1.0
+                        (summary 0.25 point)
+                        (if gnus-carpal '(summary-carpal 4))
+                        (article 1.0))
+              (vertical ((height . 5) (width . 15)
+                         (user-position . t)
+                         (left . -1) (top . 1))
+                        (picons 1.0))))
+      (gnus-use-trees
+       '(vertical 1.0
+                 (summary 0.25 point)
+                 (tree 0.25)
+                 (article 1.0)))
+      (t
+       '(vertical 1.0
+                (summary 0.25 point)
+                (if gnus-carpal '(summary-carpal 4))
+                (if gnus-use-trees '(tree 0.25))
+                (article 1.0)))))
+    (server
+     (vertical 1.0
+              (server 1.0 point)
+              (if gnus-carpal '(server-carpal 2))))
+    (browse
+     (vertical 1.0
+              (browse 1.0 point)
+              (if gnus-carpal '(browse-carpal 2))))
+    (message
+     (vertical 1.0
+              (message 1.0 point)))
+    (pick
+     (vertical 1.0
+              (article 1.0 point)))
+    (info
+     (vertical 1.0
+              (info 1.0 point)))
+    (summary-faq
+     (vertical 1.0
+              (summary 0.25)
+              (faq 1.0 point)))
+    (edit-group
+     (vertical 1.0
+              (group 0.5)
+              (edit-group 1.0 point)))
+    (edit-server
+     (vertical 1.0
+              (server 0.5)
+              (edit-server 1.0 point)))
+    (edit-score
+     (vertical 1.0
+              (summary 0.25)
+              (edit-score 1.0 point)))
+    (post
+     (vertical 1.0
+              (post 1.0 point)))
+    (reply
+     (vertical 1.0
+              (article-copy 0.5)
+              (message 1.0 point)))
+    (forward
+     (vertical 1.0
+              (message 1.0 point)))
+    (reply-yank
+     (vertical 1.0
+              (message 1.0 point)))
+    (mail-bounce
+     (vertical 1.0
+              (article 0.5)
+              (message 1.0 point)))
+    (draft
+     (vertical 1.0
+              (draft 1.0 point)))
+    (pipe
+     (vertical 1.0
+              (summary 0.25 point)
+              (if gnus-carpal '(summary-carpal 4))
+              ("*Shell Command Output*" 1.0)))
+    (bug
+     (vertical 1.0
+              ("*Gnus Help Bug*" 0.5)
+              ("*Gnus Bug*" 1.0 point)))
+    (compose-bounce
+     (vertical 1.0
+              (article 0.5)
+              (message 1.0 point))))
   "Window configuration for all possible Gnus buffers.
 This variable is a list of lists.  Each of these lists has a NAME and
-a RULE.  The NAMEs are commonsense names like `group', which names a
+a RULE.         The NAMEs are commonsense names like `group', which names a
 rule used when displaying the group buffer; `summary', which names a
 rule for what happens when you enter a group and do not display an
 article buffer; and so on.  See the value of this variable for a
 complete list of NAMEs.
 
-Each RULE is a list of vectors.  The first element in this vector is
+Each RULE is a list of vectors.         The first element in this vector is
 the name of the buffer to be displayed; the second element is the
 percentage of the screen this buffer is to occupy (a number in the
 0.0-0.99 range); the optional third element is `point', which should
@@ -754,9 +948,13 @@ buffer configuration.")
     (server-carpal . gnus-carpal-server-buffer)
     (browse-carpal . gnus-carpal-browse-buffer)
     (edit-score . gnus-score-edit-buffer)
-    (mail . gnus-mail-buffer)
-    (post . gnus-post-news-buffer)
-    (faq . gnus-faq-buffer))
+    (message . gnus-message-buffer)
+    (faq . gnus-faq-buffer)
+    (picons . "*Picons*")
+    (tree . gnus-tree-buffer)
+    (info . gnus-info-buffer)
+    (article-copy . gnus-article-copy)
+    (draft . gnus-draft-buffer))
   "Mapping from short symbols to buffer names or buffer variables.")
 
 (defvar gnus-carpal nil
@@ -769,10 +967,10 @@ 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>. 
+;; <h.b.furuseth@usit.uio.no>.
 (defvar gnus-subscribe-options-newsgroup-method
   (function gnus-subscribe-alphabetically)
   "*This function is called to subscribe newsgroups mentioned on \"options -n\" lines.
@@ -799,11 +997,16 @@ hierarchy in its entirety.")
   "*Function used for sorting the group buffer.
 This function will be called with group info entries as the arguments
 for the groups to be sorted.  Pre-made functions include
-`gnus-group-sort-by-alphabet', `gnus-group-sort-by-unread' and
-`gnus-group-sort-by-level'")
+`gnus-group-sort-by-alphabet', `gnus-group-sort-by-unread',
+`gnus-group-sort-by-level', `gnus-group-sort-by-score', and
+`gnus-group-sort-by-rank'.
+
+This variable can also be a list of sorting functions. In that case,
+the most significant sort function should be the last function in the
+list.")
 
 ;; Mark variables suggested by Thomas Michanek
-;; <Thomas.Michanek@telelogic.se>. 
+;; <Thomas.Michanek@telelogic.se>.
 (defvar gnus-unread-mark ? 
   "*Mark used for unread articles.")
 (defvar gnus-ticked-mark ?!
@@ -818,6 +1021,8 @@ for the groups to be sorted.  Pre-made functions include
   "*Mark used for expirable articles.")
 (defvar gnus-killed-mark ?K
   "*Mark used for killed articles.")
+(defvar gnus-souped-mark ?F
+  "*Mark used for killed articles.")
 (defvar gnus-kill-file-mark ?X
   "*Mark used for articles killed by kill files.")
 (defvar gnus-low-score-mark ?Y
@@ -826,10 +1031,16 @@ for the groups to be sorted.  Pre-made functions include
   "*Mark used for articles that are caught up.")
 (defvar gnus-replied-mark ?A
   "*Mark used for articles that have been replied to.")
-(defvar gnus-process-mark ?# 
+(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
   "*Mark used for ancient articles.")
+(defvar gnus-sparse-mark ?Q
+  "*Mark used for sparsely reffed articles.")
 (defvar gnus-canceled-mark ?G
   "*Mark used for canceled articles.")
 (defvar gnus-score-over-mark ?+
@@ -840,8 +1051,6 @@ for the groups to be sorted.  Pre-made functions include
   "*There is no thread under the article.")
 (defvar gnus-not-empty-thread-mark ?=
   "*There is a thread under the article.")
-(defvar gnus-dummy-mark ?Z
-  "*This is a dummy article.")
 
 (defvar gnus-view-pseudo-asynchronously nil
   "*If non-nil, Gnus will view pseudo-articles asynchronously.")
@@ -856,7 +1065,10 @@ 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-group-line-format "%M%S%p%5y: %(%g%)\n"
+(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%)%l\n"
   "*Format of group lines.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
@@ -878,21 +1090,23 @@ with some simple extensions.
 %o    Moderated group (char, \"m\")
 %p    Process mark (char)
 %O    Moderated group (string, \"(m)\" or \"\")
+%P    Topic indentation (string)
+%l    Whether there are GroupLens predictions for this group (string)
 %n    Select from where (string)
 %z    A string that look like `<%s:%n>' if a foreign select method is used
-%u    User defined specifier. The next character in the format string should
+%u    User defined specifier.  The next character in the format string should
       be a letter.  Gnus will call the function gnus-user-format-function-X,
-      where X is the letter following %u. The function will be passed the
-      current header as argument. The function should return a string, which
+      where X is the letter following %u.  The function will be passed the
+      current header as argument.  The function should return a string, which
       will be inserted into the buffer just like information from any other
       group specifier.
 
 Text between %( and %) will be highlighted with `gnus-mouse-face' when
 the mouse point move inside the area.  There can only be one such area.
 
-Note that this format specification is not always respected. For
+Note that this format specification is not always respected.  For
 reasons of efficiency, when listing killed groups, this specification
-is ignored altogether. If the spec is changed considerably, your
+is ignored altogether. If the spec is changed considerably, your
 output may end up looking strange when listing both alive and killed
 groups.
 
@@ -900,7 +1114,7 @@ If you use %o or %O, reading the active file will be slower and quite
 a bit of extra memory will be used. %D will also worsen performance.
 Also note that if you change the format specification to include any
 of these specs, you must probably re-start Gnus to see them go into
-effect.") 
+effect.")
 
 (defvar gnus-summary-line-format "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"
   "*The format specification of the lines in the summary buffer.
@@ -925,8 +1139,8 @@ with some simple extensions.
 %I   Indentation based on thread level (a string of spaces)
 %T   A string with two possible values: 80 spaces if the article
      is on thread level two or larger and 0 spaces on level one
-%R   \"R\" if this article has been replied to, \" \" otherwise (character)
-%U   Status of this article (character, \"D\", \"K\", \"-\" or \" \")
+%R   \"A\" if this article has been replied to, \" \" otherwise (character)
+%U   Status of this article (character, \"R\", \"K\", \"-\" or \" \")
 %[   Opening bracket (character, \"[\" or \"<\")
 %]   Closing bracket (character, \"]\" or \">\")
 %>   Spaces of length thread-level (string)
@@ -935,77 +1149,102 @@ with some simple extensions.
 %z   Article zcore (character)
 %t   Number of articles under the current thread (number).
 %e   Whether the thread is empty or not (character).
-%u   User defined specifier. The next character in the format string should
+%l   GroupLens score (string).
+%u   User defined specifier.  The next character in the format string should
      be a letter.  Gnus will call the function gnus-user-format-function-X,
-     where X is the letter following %u. The function will be passed the
-     current header as argument. The function should return a string, which
+     where X is the letter following %u.  The function will be passed the
+     current header as argument.  The function should return a string, which
      will be inserted into the summary just like information from any other
      summary specifier.
 
 Text between %( and %) will be highlighted with `gnus-mouse-face'
-when the mouse point is placed inside the area.  There can only be one
+when the mouse point is placed inside the area.         There can only be one
 such area.
 
 The %U (status), %R (replied) and %z (zcore) specs have to be handled
-with care. For reasons of efficiency, Gnus will compute what column
-these characters will end up in, and \"hard-code\" that. This means that
-it is illegal to have these specs after a variable-length spec. Well,
+with care.  For reasons of efficiency, Gnus will compute what column
+these characters will end up in, and \"hard-code\" that.  This means that
+it is illegal to have these specs after a variable-length spec.         Well,
 you might not be arrested, but your summary buffer will look strange,
 which is bad enough.
 
 The smart choice is to have these specs as for to the left as
-possible. 
+possible.
 
 This restriction may disappear in later versions of Gnus.")
 
-(defvar gnus-summary-dummy-line-format "*  :                          : %S\n"
+(defvar gnus-summary-dummy-line-format
+  "*  %(:                          :%) %S\n"
   "*The format specification for the dummy roots in the summary buffer.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
 
 %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)
-    ("nnspool" post)
-    ("nnvirtual" none virtual prompt-address) 
-    ("nnmbox" mail respool
-    ("nnml" mail respool)
-    ("nnmh" mail respool
-    ("nndir" none prompt-address address)
-    ("nneething" none prompt-address)
-    ("nndigest" none) 
-    ("nndoc" none prompt-address) 
-    ("nnbabyl" mail respool) 
-    ("nnkiboze" post virtual) 
-    ;;("nnsoup" post)
-    ("nnfolder" mail respool))
+    ("nnspool" post address)
+    ("nnvirtual" post-mail virtual prompt-address)
+    ("nnmbox" mail respool address)
+    ("nnml" mail respool address)
+    ("nnmh" mail respool address)
+    ("nndir" post-mail prompt-address address)
+    ("nneething" none address prompt-address)
+    ("nndoc" none address prompt-address)
+    ("nnbabyl" mail address respool)
+    ("nnkiboze" post address virtual)
+    ("nnsoup" post-mail address)
+    ("nndraft" post-mail)
+    ("nnfolder" mail respool address))
   "An alist of valid select methods.
 The first element of each list lists should be a string with the name
-of the select method. The other elements may be be the category of
+of the select method.  The other elements may be be the category of
 this method (ie. `post', `mail', `none' or whatever) or other
 properties that this method has (like being respoolable).
 If you implement a new select method, all you should have to change is
-this variable. I think.")
+this variable. I think.")
 
-(defvar gnus-updated-mode-lines '(group article summary)
+(defvar gnus-updated-mode-lines '(group article summary tree)
   "*List of buffers that should update their mode lines.
-The list may contain the symbols `group', `article' and `summary'. If
+The list may contain the symbols `group', `article' and `summary'.  If
 the corresponding symbol is present, Gnus will keep that mode line
-updated with information that may be pertinent. 
+updated with information that may be pertinent.
 If this variable is nil, screen refresh may be quicker.")
 
 ;; Added by Keinonen Kari <kk85613@cs.tut.fi>.
-(defvar gnus-mode-non-string-length 21
+(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.")
@@ -1018,7 +1257,11 @@ of the modeline intact.")
 (defvar gnus-summary-mark-below nil
   "*Mark all articles with a score below this variable as read.
 This variable is local to each summary buffer and usually set by the
-score file.")  
+score file.")
+
+(defvar gnus-article-sort-functions '(gnus-article-sort-by-number)
+  "*List of functions used for sorting articles in the summary buffer.
+This variable is only used when not using a threaded display.")
 
 (defvar gnus-thread-sort-functions '(gnus-thread-sort-by-number)
   "*List of functions used for sorting threads in the summary buffer.
@@ -1026,7 +1269,9 @@ By default, threads are sorted by article number.
 
 Each function takes two threads and return non-nil if the first thread
 should be sorted before the other.  If you use more than one function,
-the primary sort function should be the last.
+the primary sort function should be the last.  You should probably
+always include `gnus-thread-sort-by-number' in the list of sorting
+functions -- preferably first.
 
 Ready-mady functions include `gnus-thread-sort-by-number',
 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
@@ -1041,14 +1286,28 @@ 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.
+Note that this variable only deals with new groups.  It has no effect
+whatsoever on old groups.")
+
 (defvar gnus-options-subscribe nil
   "*All new groups matching this regexp will be subscribed unconditionally.
-Note that this variable deals only with new newsgroups.  This variable
+Note that this variable deals only with new newsgroups.         This variable
 does not affect old newsgroups.")
 
 (defvar gnus-options-not-subscribe nil
   "*All new groups matching this regexp will be ignored.
-Note that this variable deals only with new newsgroups.  This variable
+Note that this variable deals only with new newsgroups.         This variable
 does not affect old (already subscribed) newsgroups.")
 
 (defvar gnus-auto-expirable-newsgroups nil
@@ -1056,12 +1315,23 @@ does not affect old (already subscribed) newsgroups.")
 If non-nil, this should be a regexp that should match all groups in
 which to perform auto-expiry.  This only makes sense for mail groups.")
 
+(defvar gnus-total-expirable-newsgroups nil
+  "*Groups in which to perform expiry of all read articles.
+Use with extreme caution.  All groups that match this regexp will be
+expiring - which means that all read articles will be deleted after
+(say) one week.         (This only goes for mail groups and the like, of
+course.)")
+
+(defvar gnus-group-uncollapsed-levels 1
+  "Number of group name elements to leave alone when making a short group name.")
+
 (defvar gnus-hidden-properties '(invisible t intangible t)
   "Property list to use for hiding text.")
 
 (defvar gnus-modtime-botch nil
-  "*Non-nil means .newsrc should be deleted prior to save.  Its use is
-due to the bogus appearance that .newsrc was modified on disc.")
+  "*Non-nil means .newsrc should be deleted prior to save.  
+Its use is due to the bogus appearance that .newsrc was modified on
+disc.")
 
 ;; Hooks.
 
@@ -1075,17 +1345,23 @@ This hook is run before any variables are set in the summary buffer.")
 (defvar gnus-article-mode-hook nil
   "*A hook for Gnus article mode.")
 
-(defun gnus-summary-prepare-exit-hook nil
+(defvar gnus-summary-prepare-exit-hook nil
   "*A hook called when preparing to exit from the summary buffer.
 It calls `gnus-summary-expire-articles' by default.")
 (add-hook 'gnus-summary-prepare-exit-hook 'gnus-summary-expire-articles)
 
-(defun gnus-summary-exit-hook nil
+(defvar gnus-summary-exit-hook nil
   "*A hook called on exit from the summary buffer.")
 
+(defvar gnus-group-catchup-group-hook nil
+  "*A hook run when catching up a group from the group buffer.")
+
 (defvar gnus-open-server-hook nil
   "*A hook called just before opening connection to the news server.")
 
+(defvar gnus-load-hook nil
+  "*A hook run while Gnus is loaded.")
+
 (defvar gnus-startup-hook nil
   "*A hook called at startup.
 This hook is called after Gnus is connected to the NNTP server.")
@@ -1093,12 +1369,15 @@ This hook is called after Gnus is connected to the NNTP server.")
 (defvar gnus-get-new-news-hook nil
   "*A hook run just before Gnus checks for new news.")
 
+(defvar gnus-after-getting-new-news-hook nil
+  "*A hook run after Gnus checks for new news.")
+
 (defvar gnus-group-prepare-function 'gnus-group-prepare-flat
   "*A function that is called to generate the group buffer.
 The function is called with three arguments: The first is a number;
 all group with a level less or equal to that number should be listed,
-if the second is non-nil, empty groups should also be displayed. If
-the third is non-nil, it is a number. No groups with a level lower
+if the second is non-nil, empty groups should also be displayed.  If
+the third is non-nil, it is a number.  No groups with a level lower
 than this number should be displayed.
 
 The only current function implemented is `gnus-group-prepare-flat'.")
@@ -1111,6 +1390,11 @@ If you want to modify the group buffer, you can use this hook.")
   "*A hook called after the summary buffer has been generated.
 If you want to modify the summary buffer, you can use this hook.")
 
+(defvar gnus-summary-generate-hook nil
+  "*A hook run just before generating the summary buffer.
+This hook is commonly used to customize threading variables and the
+like.")
+
 (defvar gnus-article-prepare-hook nil
   "*A hook called after an article has been prepared in the article buffer.
 If you want to run a special decoding program like nkf, use this hook.")
@@ -1118,9 +1402,9 @@ If you want to run a special decoding program like nkf, use this hook.")
 ;(defvar gnus-article-display-hook nil
 ;  "*A hook called after the article is displayed in the article buffer.
 ;The hook is designed to change the contents of the article
-;buffer. Typical functions that this hook may contain are
+;buffer.  Typical functions that this hook may contain are
 ;`gnus-article-hide-headers' (hide selected headers),
-;`gnus-article-maybe-highlight' (perform fancy article highlighting), 
+;`gnus-article-maybe-highlight' (perform fancy article highlighting),
 ;`gnus-article-hide-signature' (hide signature) and
 ;`gnus-article-treat-overstrike' (turn \"^H_\" into bold characters).")
 ;(add-hook 'gnus-article-display-hook 'gnus-article-hide-headers-if-wanted)
@@ -1131,7 +1415,7 @@ If you want to run a special decoding program like nkf, use this hook.")
   "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -"
   "String or function to be executed to display an X-Face header.
 If it is a string, the command will be executed in a sub-shell
-asynchronously. The compressed face will be piped to this command.") 
+asynchronously.         The compressed face will be piped to this command.")
 
 (defvar gnus-article-x-face-too-ugly nil
   "Regexp matching posters whose face shouldn't be shown automatically.")
@@ -1147,17 +1431,14 @@ following hook:
       (list
        (lambda ()
          (mapcar (lambda (header)
-                    (header-set-subject
+                    (mail-header-set-subject
                      header
                      (gnus-simplify-subject
-                      (header-subject header) 're-only)))
+                      (mail-header-subject header) 're-only)))
                  gnus-newsgroup-headers))))")
 
-(defvar gnus-select-article-hook
-  '(gnus-summary-show-thread)
-  "*A hook called when an article is selected.
-The default hook shows conversation thread subtrees of the selected
-article automatically using `gnus-summary-show-thread'.")
+(defvar gnus-select-article-hook nil
+  "*A hook called when an article is selected.")
 
 (defvar gnus-apply-kill-hook '(gnus-apply-kill-file)
   "*A hook called to apply kill files to a group.
@@ -1165,7 +1446,7 @@ This hook is intended to apply a kill file to the selected newsgroup.
 The function `gnus-apply-kill-file' is called by default.
 
 Since a general kill file is too heavy to use only for a few
-newsgroups, I recommend you to use a lighter hook function. For
+newsgroups, I recommend you to use a lighter hook function.  For
 example, if you'd like to apply a kill file to articles which contains
 a string `rmgroup' in subject in newsgroup `control', you can use the
 following hook:
@@ -1177,16 +1458,14 @@ following hook:
                 (gnus-kill \"Subject\" \"rmgroup\")
                 (gnus-expunge \"X\"))))))")
 
-(defvar gnus-visual-mark-article-hook 
+(defvar gnus-visual-mark-article-hook
   (list 'gnus-highlight-selected-summary)
   "*Hook run after selecting an article in the summary buffer.
 It is meant to be used for highlighting the article in some way.  It
 is not run if `gnus-visual' is nil.")
 
-(defvar gnus-prepare-article-hook (list 'gnus-inews-insert-signature)
-  "*A hook called after preparing body, but before preparing header headers.
-The default hook (`gnus-inews-insert-signature') inserts a signature
-file specified by the variable `gnus-signature-file'.")
+(defvar gnus-parse-headers-hook nil
+  "*A hook called before parsing the headers.")
 
 (defvar gnus-exit-group-hook nil
   "*A hook called when exiting (not quitting) summary mode.")
@@ -1197,10 +1476,21 @@ file specified by the variable `gnus-signature-file'.")
 (defvar gnus-exit-gnus-hook nil
   "*A hook called when exiting Gnus.")
 
+(defvar gnus-after-exiting-gnus-hook nil
+  "*A hook called after exiting Gnus.")
+
 (defvar gnus-save-newsrc-hook nil
-  "*A hook called when saving the newsrc file.")
+  "*A hook called before saving any of the newsrc files.")
+
+(defvar gnus-save-quick-newsrc-hook nil
+  "*A hook called just before saving the quick newsrc file.
+Can be used to turn version control on or off.")
 
-(defvar gnus-summary-update-hook 
+(defvar gnus-save-standard-newsrc-hook nil
+  "*A hook called just before saving the standard newsrc file.
+Can be used to turn version control on or off.")
+
+(defvar gnus-summary-update-hook
   (list 'gnus-summary-highlight-line)
   "*A hook called when a summary line is changed.
 The hook will not be called if `gnus-visual' is nil.
@@ -1209,29 +1499,67 @@ The default function `gnus-summary-highlight-line' will
 highlight the line according to the `gnus-summary-highlight'
 variable.")
 
-(defvar gnus-mark-article-hook (list 'gnus-summary-mark-unread-as-read)
+(defvar gnus-group-update-hook '(gnus-group-highlight-line)
+  "*A hook called when a group line is changed.
+The hook will not be called if `gnus-visual' is nil.
+
+The default function `gnus-group-highlight-line' will
+highlight the line according to the `gnus-group-highlight'
+variable.")
+
+(defvar gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read)
   "*A hook called when an article is selected for the first time.
 The hook is intended to mark an article as read (or unread)
 automatically when it is selected.")
 
+(defvar gnus-group-change-level-function nil
+  "Function run when a group level is changed.
+It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
+
 ;; Remove any hilit infestation.
 (add-hook 'gnus-startup-hook
          (lambda ()
            (remove-hook 'gnus-summary-prepare-hook
                         'hilit-rehighlight-buffer-quietly)
            (remove-hook 'gnus-summary-prepare-hook 'hilit-install-line-hooks)
-           (setq gnus-mark-article-hook '(gnus-summary-mark-unread-as-read))
+           (setq gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read))
            (remove-hook 'gnus-article-prepare-hook
                         'hilit-rehighlight-buffer-quietly)))
 
-
 \f
 ;; Internal variables
 
+(defvar gnus-server-alist nil
+  "List of available servers.")
+
+(defvar gnus-group-indentation-function nil)
+
+(defvar gnus-topic-indentation "") ;; Obsolete variable.
+
+(defvar gnus-goto-missing-group-function nil)
+
+(defvar gnus-override-subscribe-method nil)
+
+(defvar gnus-group-goto-next-group-function nil
+  "Function to override finding the next group after listing groups.")
+
+(defconst gnus-article-mark-lists
+  '((marked . tick) (replied . reply)
+    (expirable . expire) (killed . killed)
+    (bookmarks . bookmark) (dormant . dormant)
+    (scored . score) (saved . save)
+    (cached . cache)
+    ))
+
 ;; Avoid highlighting in kill files.
 (defvar gnus-summary-inhibit-highlight nil)
 (defvar gnus-newsgroup-selected-overlay nil)
 
+(defvar gnus-inhibit-hiding nil)
+(defvar gnus-group-indentation "")
+(defvar gnus-inhibit-limiting nil)
+(defvar gnus-created-frames nil)
+
 (defvar gnus-article-mode-map nil)
 (defvar gnus-dribble-buffer nil)
 (defvar gnus-headers-retrieved-by nil)
@@ -1240,102 +1568,126 @@ automatically when it is selected.")
 (defvar gnus-article-check-size nil)
 
 (defvar gnus-current-score-file nil)
-(defvar gnus-internal-global-score-files nil)
-(defvar gnus-score-file-list nil)
+(defvar gnus-newsgroup-adaptive-score-file nil)
+(defvar gnus-scores-exclude-files nil)
 
+(defvar gnus-opened-servers nil)
 
 (defvar gnus-current-move-group nil)
 
 (defvar gnus-newsgroup-dependencies nil)
-(defvar gnus-newsgroup-threads nil)
 (defvar gnus-newsgroup-async nil)
 (defconst gnus-group-edit-buffer "*Gnus edit newsgroup*")
 
 (defvar gnus-newsgroup-adaptive nil)
 
 (defvar gnus-summary-display-table nil)
-
-(defconst gnus-group-line-format-alist
-  (list (list ?M 'marked ?c)
-       (list ?S 'subscribed ?c)
-       (list ?L 'level ?d)
-       (list ?N 'number ?s)
-       (list ?I 'number-of-dormant ?d)
-       (list ?T 'number-of-ticked ?d)
-       (list ?R 'number-of-read ?s)
-       (list ?t 'number-total ?d)
-       (list ?y 'number-of-unread-unticked ?s)
-       (list ?i 'number-of-ticked-and-dormant ?d)
-       (list ?g 'group ?s)
-       (list ?G 'qualified-group ?s)
-       (list ?D 'newsgroup-description ?s)
-       (list ?o 'moderated ?c)
-       (list ?O 'moderated-string ?s)
-       (list ?p 'process-marked ?c)
-       (list ?s 'news-server ?s)
-       (list ?n 'news-method ?s)
-       (list ?z 'news-method-string ?s)
-       (list ?u 'user-defined ?s)))
-
-(defconst gnus-summary-line-format-alist 
-  (list (list ?N 'number ?d)
-       (list ?S 'subject ?s)
-       (list ?s 'subject-or-nil ?s)
-       (list ?n 'name ?s)
-       (list ?A '(car (cdr (funcall gnus-extract-address-components from)))
-             ?s)
-       (list ?a '(or (car (funcall gnus-extract-address-components from)) 
-                     from) ?s)
-       (list ?F 'from ?s)
-       (list ?x (macroexpand '(header-xref header)) ?s)
-       (list ?D (macroexpand '(header-date header)) ?s)
-       (list ?d '(gnus-dd-mmm (header-date header)) ?s)
-       (list ?M (macroexpand '(header-id header)) ?s)
-       (list ?r (macroexpand '(header-references header)) ?s)
-       (list ?c '(or (header-chars header) 0) ?d)
-       (list ?L 'lines ?d)
-       (list ?I 'indentation ?s)
-       (list ?T '(if (= level 0) "" (make-string (frame-width) ? )) ?s)
-       (list ?R 'replied ?c)
-       (list ?\[ 'opening-bracket ?c)
-       (list ?\] 'closing-bracket ?c)
-       (list ?\> '(make-string level ? ) ?s)
-       (list ?\< '(make-string (max 0 (- 20 level)) ? ) ?s)
-       (list ?i 'score ?d)
-       (list ?z 'score-char ?c)
-       (list ?U 'unread ?c)
-       (list ?t '(gnus-summary-number-of-articles-in-thread 
-                  (and (boundp 'thread) (car thread)))
-             ?d)
-       (list ?e '(gnus-summary-number-of-articles-in-thread 
-                  (and (boundp 'thread) (car thread)) t)
-             ?c)
-       (list ?u 'user-defined ?s))
+(defvar gnus-summary-display-article-function nil)
+
+(defvar gnus-summary-highlight-line-function nil
+  "Function called after highlighting a summary line.")
+
+(defvar gnus-group-line-format-alist
+  `((?M gnus-tmp-marked-mark ?c)
+    (?S gnus-tmp-subscribed ?c)
+    (?L gnus-tmp-level ?d)
+    (?N (cond ((eq number t) "*" )
+             ((numberp number) 
+              (int-to-string
+               (+ number
+                  (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
+                  (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))))))
+             (t number)) ?s)
+    (?R gnus-tmp-number-of-read ?s)
+    (?t gnus-tmp-number-total ?d)
+    (?y gnus-tmp-number-of-unread ?s)
+    (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d)
+    (?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d)
+    (?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
+          (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d)
+    (?g gnus-tmp-group ?s)
+    (?G gnus-tmp-qualified-group ?s)
+    (?c (gnus-short-group-name gnus-tmp-group) ?s)
+    (?D gnus-tmp-newsgroup-description ?s)
+    (?o gnus-tmp-moderated ?c)
+    (?O gnus-tmp-moderated-string ?s)
+    (?p gnus-tmp-process-marked ?c)
+    (?s gnus-tmp-news-server ?s)
+    (?n gnus-tmp-news-method ?s)
+    (?P gnus-group-indentation ?s)
+    (?l gnus-tmp-grouplens ?s)
+    (?z gnus-tmp-news-method-string ?s)
+    (?u gnus-tmp-user-defined ?s)))
+
+(defvar gnus-summary-line-format-alist
+  `((?N ,(macroexpand '(mail-header-number gnus-tmp-header)) ?d)
+    (?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
+    (?s gnus-tmp-subject-or-nil ?s)
+    (?n gnus-tmp-name ?s)
+    (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
+       ?s)
+    (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
+           gnus-tmp-from) ?s)
+    (?F gnus-tmp-from ?s)
+    (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
+    (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
+    (?d (gnus-dd-mmm (mail-header-date gnus-tmp-header)) ?s)
+    (?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
+    (?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
+    (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
+    (?L gnus-tmp-lines ?d)
+    (?I gnus-tmp-indentation ?s)
+    (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
+    (?R gnus-tmp-replied ?c)
+    (?\[ gnus-tmp-opening-bracket ?c)
+    (?\] gnus-tmp-closing-bracket ?c)
+    (?\> (make-string gnus-tmp-level ? ) ?s)
+    (?\< (make-string (max 0 (- 20 gnus-tmp-level)) ? ) ?s)
+    (?i gnus-tmp-score ?d)
+    (?z gnus-tmp-score-char ?c)
+    (?l (bbb-grouplens-score gnus-tmp-header) ?s)
+    (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
+    (?U gnus-tmp-unread ?c)
+    (?t (gnus-summary-number-of-articles-in-thread
+        (and (boundp 'thread) (car thread)) gnus-tmp-level)
+       ?d)
+    (?e (gnus-summary-number-of-articles-in-thread
+        (and (boundp 'thread) (car thread)) gnus-tmp-level t)
+       ?c)
+    (?u gnus-tmp-user-defined ?s))
   "An alist of format specifications that can appear in summary lines,
 and what variables they correspond with, along with the type of the
 variable (string, integer, character, etc).")
 
-(defconst gnus-summary-dummy-line-format-alist
-  (list (list ?S 'subject ?s)
-       (list ?N 'number ?d)
-       (list ?u 'user-defined ?s)))
-
-(defconst gnus-summary-mode-line-format-alist 
-  (list (list ?G 'group-name ?s)
-       (list ?g '(gnus-short-group-name group-name) ?s)
-       (list ?A 'article-number ?d)
-       (list ?Z 'unread-and-unselected ?s)
-       (list ?V 'gnus-version ?s)
-       (list ?U 'unread ?d)
-       (list ?S 'subject ?s)
-       (list ?e 'unselected ?d)
-       (list ?u 'user-defined ?s)
-       (list ?s '(gnus-current-score-file-nondirectory) ?s)))
-
-(defconst gnus-group-mode-line-format-alist 
-  (list (list ?S 'news-server ?s)
-       (list ?M 'news-method ?s)
-       (list ?u 'user-defined ?s)))
+(defvar gnus-summary-dummy-line-format-alist
+  `((?S gnus-tmp-subject ?s)
+    (?N gnus-tmp-number ?d)
+    (?u gnus-tmp-user-defined ?s)))
+
+(defvar gnus-summary-mode-line-format-alist
+  `((?G gnus-tmp-group-name ?s)
+    (?g (gnus-short-group-name gnus-tmp-group-name) ?s)
+    (?p (gnus-group-real-name gnus-tmp-group-name) ?s)
+    (?A gnus-tmp-article-number ?d)
+    (?Z gnus-tmp-unread-and-unselected ?s)
+    (?V gnus-version ?s)
+    (?U gnus-tmp-unread ?d)
+    (?S gnus-tmp-subject ?s)
+    (?e gnus-tmp-unselected ?d)
+    (?u gnus-tmp-user-defined ?s)
+    (?d (length gnus-newsgroup-dormant) ?d)
+    (?t (length gnus-newsgroup-marked) ?d)
+    (?r (length gnus-newsgroup-reads) ?d)
+    (?E gnus-newsgroup-expunged-tally ?d)
+    (?s (gnus-current-score-file-nondirectory) ?s)))
+
+(defvar gnus-article-mode-line-format-alist
+  gnus-summary-mode-line-format-alist)
+
+(defvar gnus-group-mode-line-format-alist
+  `((?S gnus-tmp-news-server ?s)
+    (?M gnus-tmp-news-method ?s)
+    (?u gnus-tmp-user-defined ?s)))
 
 (defvar gnus-have-read-active-file nil)
 
@@ -1343,7 +1695,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 "(ding) Gnus v0.99.23"
+(defconst gnus-version "September Gnus v0.69"
   "Version number for this version of Gnus.")
 
 (defvar gnus-info-nodes
@@ -1352,9 +1704,6 @@ variable (string, integer, character, etc).")
     (gnus-article-mode         "(gnus)The Article Buffer"))
   "Assoc list of major modes and related Info nodes.")
 
-(defvar gnus-documentation-group-file "~/dgnus/lisp/doc.txt"
-  "The location of the Gnus documentation group.")
-
 (defvar gnus-group-buffer "*Group*")
 (defvar gnus-summary-buffer "*Summary*")
 (defvar gnus-article-buffer "*Article*")
@@ -1362,33 +1711,39 @@ variable (string, integer, character, etc).")
 
 (defvar gnus-work-buffer " *gnus work*")
 
+(defvar gnus-original-article-buffer " *Original Article*")
+(defvar gnus-original-article nil)
+
 (defvar gnus-buffer-list nil
   "Gnus buffers that should be killed on exit.")
 
-(defvar gnus-server-alist nil
-  "List of available servers.")
+(defvar gnus-slave nil
+  "Whether this Gnus is a slave or not.")
 
 (defvar gnus-variable-list
   '(gnus-newsrc-options gnus-newsrc-options-n
-    gnus-newsrc-last-checked-date 
+    gnus-newsrc-last-checked-date
     gnus-newsrc-alist gnus-server-alist
-    gnus-killed-list gnus-zombie-list)
+    gnus-killed-list gnus-zombie-list
+    gnus-topic-topology gnus-topic-alist
+    gnus-format-specs)
   "Gnus variables saved in the quick startup file.")
 
-(defvar gnus-overload-functions
-  '((news-inews gnus-inews-news "rnewspost"))
-  "Functions overloaded by gnus.
-It is a list of `(original overload &optional file)'.")
-
 (defvar gnus-newsrc-options nil
   "Options line in the .newsrc file.")
 
 (defvar gnus-newsrc-options-n nil
-  "List of regexps representing groups to be subscribed/ignored unconditionally.") 
+  "List of regexps representing groups to be subscribed/ignored unconditionally.")
 
 (defvar gnus-newsrc-last-checked-date nil
   "Date Gnus last asked server for new newsgroups.")
 
+(defvar gnus-topic-topology nil
+  "The complete topic hierarchy.")
+
+(defvar gnus-topic-alist nil
+  "The complete topic-group alist.")
+
 (defvar gnus-newsrc-alist nil
   "Assoc list of read articles.
 gnus-newsrc-hashtb should be kept so that both hold the same information.")
@@ -1445,6 +1800,11 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (defvar gnus-newsgroup-auto-expire nil)
 (defvar gnus-newsgroup-active nil)
 
+(defvar gnus-newsgroup-data nil)
+(defvar gnus-newsgroup-data-reverse nil)
+(defvar gnus-newsgroup-limit nil)
+(defvar gnus-newsgroup-limits nil)
+
 (defvar gnus-newsgroup-unreads nil
   "List of unread articles in the current newsgroup.")
 
@@ -1454,12 +1814,20 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (defvar gnus-newsgroup-reads nil
   "Alist of read articles and article marks in the current newsgroup.")
 
+(defvar gnus-newsgroup-expunged-tally nil)
+
 (defvar gnus-newsgroup-marked nil
   "List of ticked articles in the current newsgroup (a subset of unread art).")
 
 (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
@@ -1482,11 +1850,17 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 
 (defvar gnus-newsgroup-headers nil
   "List of article headers in the current newsgroup.")
-(defvar gnus-newsgroup-headers-hashtb-by-number nil)
+
+(defvar gnus-newsgroup-threads nil)
+
+(defvar gnus-newsgroup-prepared nil
+  "Whether the current group has been prepared properly.")
 
 (defvar gnus-newsgroup-ancient nil
   "List of `gnus-fetch-old-headers' articles in the current newsgroup.")
 
+(defvar gnus-newsgroup-sparse nil)
+
 (defvar gnus-current-article nil)
 (defvar gnus-article-current nil)
 (defvar gnus-current-headers nil)
@@ -1498,46 +1872,46 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 ;; Save window configuration.
 (defvar gnus-prev-winconf nil)
 
-;; Format specs
-(defvar gnus-summary-line-format-spec nil)
-(defvar gnus-summary-dummy-line-format-spec nil)
-(defvar gnus-group-line-format-spec nil)
-(defvar gnus-summary-mode-line-format-spec nil)
-(defvar gnus-article-mode-line-format-spec nil)
-(defvar gnus-group-mode-line-format-spec nil)
 (defvar gnus-summary-mark-positions nil)
 (defvar gnus-group-mark-positions nil)
 
-(defvar gnus-summary-expunge-below nil)
 (defvar gnus-reffed-article-number nil)
 
-(defvar rmail-default-file (expand-file-name "~/XMBOX"))
-(defvar rmail-default-rmail-file (expand-file-name "~/XNEWS"))
+;;; Let the byte-compiler know that we know about this variable.
+(defvar rmail-default-rmail-file)
+
+(defvar gnus-cache-removable-articles nil)
 
-(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 
-    gnus-newsgroup-last-rmail gnus-newsgroup-last-mail 
-    gnus-newsgroup-last-folder gnus-newsgroup-last-file 
-    gnus-newsgroup-auto-expire gnus-newsgroup-unreads 
+(defconst gnus-summary-local-variables
+  '(gnus-newsgroup-name
+    gnus-newsgroup-begin gnus-newsgroup-end
+    gnus-newsgroup-last-rmail gnus-newsgroup-last-mail
+    gnus-newsgroup-last-folder gnus-newsgroup-last-file
+    gnus-newsgroup-auto-expire gnus-newsgroup-unreads
     gnus-newsgroup-unselected gnus-newsgroup-marked
-    gnus-newsgroup-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
-    gnus-newsgroup-headers gnus-newsgroup-headers-hashtb-by-number
+    gnus-newsgroup-headers gnus-newsgroup-threads
+    gnus-newsgroup-prepared gnus-summary-highlight-line-function
     gnus-current-article gnus-current-headers gnus-have-all-headers
     gnus-last-article gnus-article-internal-prepare-hook
     gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
     gnus-newsgroup-scored gnus-newsgroup-kill-headers
-    gnus-newsgroup-threads gnus-newsgroup-async
-    gnus-score-alist gnus-current-score-file gnus-summary-expunge-below 
+    gnus-newsgroup-async 
+    gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
     gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files
     gnus-newsgroup-history gnus-newsgroup-ancient
+    gnus-newsgroup-sparse
     (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
-    gnus-cache-removeable-articles)
+    gnus-newsgroup-adaptive-score-file
+    (gnus-newsgroup-expunged-tally . 0)
+    gnus-cache-removable-articles gnus-newsgroup-cached
+    gnus-newsgroup-data gnus-newsgroup-data-reverse
+    gnus-newsgroup-limit gnus-newsgroup-limits)
   "Variables that are buffer-local to the summary buffers.")
 
 (defconst gnus-bug-message
@@ -1545,14 +1919,14 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 ========================================
 
 The buffer below is a mail buffer.  When you press `C-c C-c', it will
-be sent to the Gnus Bug Exterminators. 
+be sent to the Gnus Bug Exterminators.
 
 At the bottom of the buffer you'll see lots of variable settings.
 Please do not delete those.  They will tell the Bug People what your
 environment is, so that it will be easier to locate the bugs.
 
 If you have found a bug that makes Emacs go \"beep\", set
-debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET') 
+debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET')
 and include the backtrace in your bug report.
 
 Please describe the bug in annoying, painstaking detail.
@@ -1565,207 +1939,184 @@ Thank you for your help in stamping out bugs.
 ;; Define some autoload functions Gnus might use.
 (eval-and-compile
 
-  ;; Various 
-  (autoload 'metamail-buffer "metamail")
-  (autoload 'Info-goto-node "info")
-  (autoload 'hexl-hex-string-to-integer "hexl")
-  (autoload 'pp "pp")
-  (autoload 'pp-to-string "pp")
-  (autoload 'pp-eval-expression "pp")
-  (autoload 'mail-extract-address-components "mail-extr")
-
-  (autoload 'nnmail-split-fancy "nnmail")
-  (autoload 'nnvirtual-catchup-group "nnvirtual")
-
-  ;; timezone
-  (autoload 'timezone-make-date-arpa-standard "timezone")
-  (autoload 'timezone-fix-time "timezone")
-  (autoload 'timezone-make-sortable-date "timezone")
-  (autoload 'timezone-make-time-string "timezone")
-
-  ;; rmail & friends
-  (autoload 'mail-position-on-field "sendmail")
-  (autoload 'mail-setup "sendmail")
-  (autoload 'rmail-output "rmailout")
-  (autoload 'news-mail-other-window "rnewspost")
-  (autoload 'news-reply-yank-original "rnewspost")
-  (autoload 'news-caesar-buffer-body "rnewspost")
-  (autoload 'rmail-insert-rmail-file-header "rmail")
-  (autoload 'rmail-count-new-messages "rmail")
-  (autoload 'rmail-show-message "rmail")
-
-  ;; gnus-soup
-  ;;(autoload 'gnus-group-brew-soup "gnus-soup" nil t)
-  ;;(autoload 'gnus-brew-soup "gnus-soup" nil t)
-  ;;(autoload 'gnus-soup-add-article "gnus-soup" nil t)
-  ;;(autoload 'gnus-soup-send-replies "gnus-soup" nil t)
-  ;;(autoload 'gnus-soup-save-areas "gnus-soup" nil t)
-  ;;(autoload 'gnus-soup-pack-packet "gnus-soup" nil t)
-  ;;(autoload 'nnsoup-pack-replies "nnsoup" nil t)
-
-  ;; gnus-mh
-  (autoload 'gnus-mail-reply-using-mhe "gnus-mh")
-  (autoload 'gnus-mail-forward-using-mhe "gnus-mh")
-  (autoload 'gnus-mail-other-window-using-mhe "gnus-mh")
-  (autoload 'gnus-summary-save-in-folder "gnus-mh")
-  (autoload 'gnus-summary-save-article-folder "gnus-mh")
-  (autoload 'gnus-Folder-save-name "gnus-mh")
-  (autoload 'gnus-folder-save-name "gnus-mh")
-
-  ;; gnus-vis misc
-  (autoload 'gnus-group-make-menu-bar "gnus-vis")
-  (autoload 'gnus-summary-make-menu-bar "gnus-vis")
-  (autoload 'gnus-server-make-menu-bar "gnus-vis")
-  (autoload 'gnus-article-make-menu-bar "gnus-vis")
-  (autoload 'gnus-browse-make-menu-bar "gnus-vis")
-  (autoload 'gnus-highlight-selected-summary "gnus-vis")
-  (autoload 'gnus-summary-highlight-line "gnus-vis")
-  (autoload 'gnus-carpal-setup-buffer "gnus-vis")
-
-  ;; gnus-vis article
-  (autoload 'gnus-article-push-button "gnus-vis" nil t)
-  (autoload 'gnus-article-press-button "gnus-vis" nil t)
-  (autoload 'gnus-article-highlight "gnus-vis" nil t)
-  (autoload 'gnus-article-highlight-some "gnus-vis" nil t)
-  (autoload 'gnus-article-hide "gnus-vis" nil t)
-  (autoload 'gnus-article-hide-signature "gnus-vis" nil t)
-  (autoload 'gnus-article-highlight-headers "gnus-vis" nil t)
-  (autoload 'gnus-article-highlight-signature "gnus-vis" nil t)
-  (autoload 'gnus-article-add-buttons "gnus-vis" nil t)
-  (autoload 'gnus-article-next-button "gnus-vis" nil t)
-  (autoload 'gnus-article-add-button "gnus-vis")
-
-  ;; gnus-cite
-  (autoload 'gnus-article-highlight-citation "gnus-cite" nil t)
-  (autoload 'gnus-article-hide-citation-maybe "gnus-cite" nil t)
-  (autoload 'gnus-article-hide-citation "gnus-cite" nil t)
-
-  ;; gnus-kill
-  (autoload 'gnus-kill "gnus-kill")
-  (autoload 'gnus-apply-kill-file-internal "gnus-kill")
-  (autoload 'gnus-kill-file-edit-file "gnus-kill")
-  (autoload 'gnus-kill-file-raise-followups-to-author "gnus-kill")
-  (autoload 'gnus-execute "gnus-kill")
-  (autoload 'gnus-expunge "gnus-kill")
-
-  ;; gnus-cache
-  (autoload 'gnus-cache-possibly-enter-article "gnus-cache")
-  (autoload 'gnus-cache-save-buffers "gnus-cache")
-  (autoload 'gnus-cache-possibly-remove-articles "gnus-cache")
-  (autoload 'gnus-cache-request-article "gnus-cache")
-  (autoload 'gnus-cache-retrieve-headers "gnus-cache")
-  (autoload 'gnus-cache-possibly-alter-active "gnus-cache")
-  (autoload 'gnus-jog-cache "gnus-cache" nil t)
-  (autoload 'gnus-cache-enter-remove-article "gnus-cache")
-
-  ;; gnus-score
-  (autoload 'gnus-summary-increase-score "gnus-score" nil t)
-  (autoload 'gnus-summary-lower-score "gnus-score" nil t)
-  (autoload 'gnus-summary-score-map "gnus-score" nil nil 'keymap)
-  (autoload 'gnus-score-save "gnus-score")
-  (autoload 'gnus-score-headers "gnus-score")
-  (autoload 'gnus-current-score-file-nondirectory "gnus-score")
-  (autoload 'gnus-score-adaptive "gnus-score")
-  (autoload 'gnus-score-remove-lines-adaptive "gnus-score")
-  (autoload 'gnus-score-find-trace "gnus-score")
-
-  ;; gnus-edit
-  (autoload 'gnus-score-customize "gnus-edit" nil t)
-
-  ;; gnus-uu
-  (autoload 'gnus-uu-extract-map "gnus-uu" nil nil 'keymap)
-  (autoload 'gnus-uu-mark-map "gnus-uu" nil nil 'keymap)
-  (autoload 'gnus-uu-digest-mail-forward "gnus-uu" nil t)
-  (autoload 'gnus-uu-digest-post-forward "gnus-uu" nil t)
-  (autoload 'gnus-uu-mark-series "gnus-uu" nil t)
-  (autoload 'gnus-uu-mark-region "gnus-uu" nil t)
-  (autoload 'gnus-uu-mark-by-regexp "gnus-uu" nil t)
-  (autoload 'gnus-uu-mark-all "gnus-uu" nil t)
-  (autoload 'gnus-uu-mark-sparse "gnus-uu" nil t)
-  (autoload 'gnus-uu-mark-thread "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-uu "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-uu-and-save "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-unshar "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-unshar-and-save "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-save "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-binhex "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-uu-view "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-uu-and-save-view "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-unshar-view "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-unshar-and-save-view "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-save-view "gnus-uu" nil t)
-  (autoload 'gnus-uu-decode-binhex-view "gnus-uu" nil t)
-
-  ;; gnus-msg
-  (autoload 'gnus-summary-send-map "gnus-msg" nil nil 'keymap)
-  (autoload 'gnus-group-post-news "gnus-msg" nil t)
-  (autoload 'gnus-group-mail "gnus-msg" nil t)
-  (autoload 'gnus-summary-post-news "gnus-msg" nil t)
-  (autoload 'gnus-summary-followup "gnus-msg" nil t)
-  (autoload 'gnus-summary-followup-with-original "gnus-msg" nil t)
-  (autoload 'gnus-summary-followup-and-reply "gnus-msg" nil t)
-  (autoload 'gnus-summary-followup-and-reply-with-original "gnus-msg" nil t)
-  (autoload 'gnus-summary-cancel-article "gnus-msg" nil t)
-  (autoload 'gnus-summary-supersede-article "gnus-msg" nil t)
-  (autoload 'gnus-post-news "gnus-msg" nil t)
-  (autoload 'gnus-inews-news "gnus-msg" nil t)
-  (autoload 'gnus-cancel-news "gnus-msg" nil t)
-  (autoload 'gnus-summary-reply "gnus-msg" nil t)
-  (autoload 'gnus-summary-reply-with-original "gnus-msg" nil t)
-  (autoload 'gnus-summary-mail-forward "gnus-msg" nil t)
-  (autoload 'gnus-summary-mail-other-window "gnus-msg" nil t)
-  (autoload 'gnus-mail-reply-using-mail "gnus-msg")
-  (autoload 'gnus-mail-yank-original "gnus-msg")
-  (autoload 'gnus-mail-send-and-exit "gnus-msg")
-  (autoload 'gnus-mail-forward-using-mail "gnus-msg")
-  (autoload 'gnus-mail-other-window-using-mail "gnus-msg")
-  (autoload 'gnus-article-mail-with-original "gnus-msg")
-  (autoload 'gnus-article-mail "gnus-msg")
-  (autoload 'gnus-bug "gnus-msg" nil t)
-
-  ;; gnus-vm
-  (autoload 'gnus-summary-save-in-vm "gnus-vm" nil t)
-  (autoload 'gnus-summary-save-article-vm "gnus-vm" nil t)
-  (autoload 'gnus-mail-forward-using-vm "gnus-vm")
-  (autoload 'gnus-mail-reply-using-vm "gnus-vm")
-  (autoload 'gnus-mail-other-window-using-vm "gnus-vm" nil t)
-  (autoload 'gnus-yank-article "gnus-vm" nil t)
-
-  )
+  ;; This little mapcar goes through the list below and marks the
+  ;; symbols in question as autoloaded functions.
+  (mapcar
+   (lambda (package)
+     (let ((interactive (nth 1 (memq ':interactive package))))
+       (mapcar
+       (lambda (function)
+         (let (keymap)
+           (when (consp function)
+             (setq keymap (car (memq 'keymap function)))
+             (setq function (car function)))
+           (autoload function (car package) nil interactive keymap)))
+       (if (eq (nth 1 package) ':interactive)
+           (cdddr package)
+         (cdr package)))))
+   '(("metamail" metamail-buffer)
+     ("info" Info-goto-node)
+     ("hexl" hexl-hex-string-to-integer)
+     ("pp" pp pp-to-string pp-eval-expression)
+     ("mail-extr" mail-extract-address-components)
+     ("nnmail" nnmail-split-fancy nnmail-article-group)
+     ("nnvirtual" nnvirtual-catchup-group)
+     ("timezone" timezone-make-date-arpa-standard timezone-fix-time
+      timezone-make-sortable-date timezone-make-time-string)
+     ("sendmail" mail-position-on-field mail-setup)
+     ("rmailout" rmail-output)
+     ("rnewspost" news-mail-other-window news-reply-yank-original
+      news-caesar-buffer-body)
+     ("rmail" rmail-insert-rmail-file-header rmail-count-new-messages
+      rmail-show-message)
+     ("gnus-soup" :interactive t
+      gnus-group-brew-soup gnus-brew-soup gnus-soup-add-article
+      gnus-soup-send-replies gnus-soup-save-areas gnus-soup-pack-packet)
+     ("nnsoup" nnsoup-pack-replies)
+     ("gnus-scomo" :interactive t gnus-score-mode)
+     ("gnus-mh" gnus-mh-mail-setup gnus-summary-save-article-folder
+      gnus-Folder-save-name gnus-folder-save-name)
+     ("gnus-mh" :interactive t gnus-summary-save-in-folder)
+     ("gnus-vis" gnus-group-make-menu-bar gnus-summary-make-menu-bar
+      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-group-highlight-line
+      gnus-article-add-button gnus-insert-next-page-button
+      gnus-insert-prev-page-button gnus-visual-turn-off-edit-menu)
+     ("gnus-vis" :interactive t
+      gnus-article-push-button gnus-article-press-button
+      gnus-article-highlight gnus-article-highlight-some
+      gnus-article-highlight-headers gnus-article-highlight-signature
+      gnus-article-add-buttons gnus-article-add-buttons-to-head
+      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)
+     ("gnus-demon" :interactive t
+      gnus-demon-init gnus-demon-cancel)
+     ("gnus-salt" gnus-highlight-selected-tree gnus-possibly-generate-tree
+      gnus-tree-open gnus-tree-close)
+     ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
+      gnus-nocem-unwanted-article-p)
+     ("gnus-srvr" gnus-enter-server-buffer gnus-server-set-info)
+     ("gnus-srvr" gnus-browse-foreign-server)
+     ("gnus-cite" :interactive t
+      gnus-article-highlight-citation gnus-article-hide-citation-maybe
+      gnus-article-hide-citation gnus-article-fill-cited-article)
+     ("gnus-kill" gnus-kill gnus-apply-kill-file-internal
+      gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author
+      gnus-execute gnus-expunge)
+     ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers
+      gnus-cache-possibly-remove-articles gnus-cache-request-article
+      gnus-cache-retrieve-headers gnus-cache-possibly-alter-active
+      gnus-cache-enter-remove-article gnus-cached-article-p
+      gnus-cache-open gnus-cache-close gnus-cache-update-article)
+     ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
+      gnus-cache-remove-article)
+     ("gnus-score" :interactive t
+      gnus-summary-increase-score gnus-summary-lower-score
+      gnus-score-flush-cache gnus-score-close
+      gnus-score-raise-same-subject-and-select
+      gnus-score-raise-same-subject gnus-score-default
+      gnus-score-raise-thread gnus-score-lower-same-subject-and-select
+      gnus-score-lower-same-subject gnus-score-lower-thread
+      gnus-possibly-score-headers)
+     ("gnus-score"
+      (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
+      gnus-current-score-file-nondirectory gnus-score-adaptive
+      gnus-score-find-trace gnus-score-file-name)
+     ("gnus-edit" :interactive t gnus-score-customize)
+     ("gnus-topic" :interactive t gnus-topic-mode)
+     ("gnus-topic" gnus-topic-remove-group)
+     ("gnus-salt" :interactive t gnus-pick-mode gnus-binary-mode)
+     ("gnus-uu" (gnus-uu-extract-map keymap) (gnus-uu-mark-map keymap))
+     ("gnus-uu" :interactive t
+      gnus-uu-digest-mail-forward gnus-uu-digest-post-forward
+      gnus-uu-mark-series gnus-uu-mark-region gnus-uu-mark-buffer
+      gnus-uu-mark-by-regexp gnus-uu-mark-all
+      gnus-uu-mark-sparse gnus-uu-mark-thread gnus-uu-decode-uu
+      gnus-uu-decode-uu-and-save gnus-uu-decode-unshar
+      gnus-uu-decode-unshar-and-save gnus-uu-decode-save
+      gnus-uu-decode-binhex gnus-uu-decode-uu-view
+      gnus-uu-decode-uu-and-save-view gnus-uu-decode-unshar-view
+      gnus-uu-decode-unshar-and-save-view gnus-uu-decode-save-view
+      gnus-uu-decode-binhex-view)
+     ("gnus-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-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
+      gnus-summary-followup-and-reply
+      gnus-summary-followup-and-reply-with-original
+      gnus-summary-cancel-article gnus-summary-supersede-article
+      gnus-post-news gnus-inews-news gnus-cancel-news
+      gnus-summary-reply gnus-summary-reply-with-original
+      gnus-summary-mail-forward gnus-summary-mail-other-window
+      gnus-bug)
+     ("gnus-picon" :interactive t gnus-article-display-picons
+      gnus-group-display-picons gnus-picons-article-display-x-face)
+     ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p 
+      gnus-grouplens-mode)
+     ("gnus-vm" gnus-vm-mail-setup)
+     ("gnus-vm" :interactive t gnus-summary-save-in-vm
+      gnus-summary-save-article-vm gnus-yank-article))))
 
 \f
 
 ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
 ;; If you want the cursor to go somewhere else, set these two
 ;; functions in some startup hook to whatever you want.
-(defalias 'gnus-summary-position-cursor 'gnus-goto-colon)
-(defalias 'gnus-group-position-cursor 'gnus-goto-colon)
+(defalias 'gnus-summary-position-point 'gnus-goto-colon)
+(defalias 'gnus-group-position-point 'gnus-goto-colon)
 
 ;;; Various macros and substs.
 
+(defun gnus-header-from (header)
+  (mail-header-from header))
+
 (defmacro gnus-eval-in-buffer-window (buffer &rest forms)
-  "Pop to BUFFER, evaluate FORMS, and then returns to original window."
-  (` (let ((GnusStartBufferWindow (selected-window)))
+  "Pop to BUFFER, evaluate FORMS, and then return to the original window."
+  (let ((tempvar (make-symbol "GnusStartBufferWindow")))
+    `(let ((,tempvar (selected-window)))
        (unwind-protect
           (progn
-            (pop-to-buffer (, buffer))
-            (,@ forms))
-        (select-window GnusStartBufferWindow)))))
+            (pop-to-buffer ,buffer)
+            ,@forms)
+        (select-window ,tempvar)))))
 
 (defmacro gnus-gethash (string hashtable)
   "Get hash value of STRING in HASHTABLE."
-  ;;(` (symbol-value (abbrev-symbol (, string) (, hashtable))))
-  ;;(` (abbrev-expansion (, string) (, hashtable)))
-  (` (symbol-value (intern-soft (, string) (, hashtable)))))
+  `(symbol-value (intern-soft ,string ,hashtable)))
 
 (defmacro gnus-sethash (string value hashtable)
-  "Set hash value. Arguments are STRING, VALUE, and HASHTABLE."
-  ;; We cannot use define-abbrev since it only accepts string as value.
-  ;; (set (intern string hashtable) value))
-  (` (set (intern (, string) (, hashtable)) (, value))))
+  "Set hash value.  Arguments are STRING, VALUE, and HASHTABLE."
+  `(set (intern ,string ,hashtable) ,value))
+
+(defmacro gnus-intern-safe (string hashtable)
+  "Set hash value.  Arguments are STRING, VALUE, and HASHTABLE."
+  `(let ((symbol (intern ,string ,hashtable)))
+     (or (boundp symbol)
+        (set symbol nil))
+     symbol))
+
+(defmacro gnus-group-unread (group)
+  "Get the currently computed number of unread articles in GROUP."
+  `(car (gnus-gethash ,group gnus-newsrc-hashtb)))
+
+(defmacro gnus-group-entry (group)
+  "Get the newsrc entry for GROUP."
+  `(gnus-gethash ,group gnus-newsrc-hashtb))
+
+(defmacro gnus-active (group)
+  "Get active info on GROUP."
+  `(gnus-gethash ,group gnus-active-hashtb))
 
-(defsubst gnus-buffer-substring (beg end)
-  (buffer-substring (match-beginning beg) (match-end end)))
+(defmacro gnus-set-active (group active)
+  "Set GROUP's active info."
+  `(gnus-sethash ,group ,active gnus-active-hashtb))
 
 ;; modified by MORIOKA Tomohiko <morioka@jaist.ac.jp>
 ;;   function `substring' might cut on a middle of multi-octet
@@ -1773,8 +2124,8 @@ Thank you for your help in stamping out bugs.
 (defun gnus-truncate-string (str width)
   (substring str 0 width))
 
-;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>. A safe way
-;; to limit the length of a string. This function is necessary since
+;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>.  A safe way
+;; to limit the length of a string.  This function is necessary since
 ;; `(substr "abc" 0 30)' pukes with "Args out of range".
 (defsubst gnus-limit-string (str width)
   (if (> (length str) width)
@@ -1783,25 +2134,31 @@ Thank you for your help in stamping out bugs.
 
 (defsubst gnus-simplify-subject-re (subject)
   "Remove \"Re:\" from subject lines."
-  (let ((case-fold-search t))
-    (if (string-match "^re: *" subject)
-       (substring subject (match-end 0))
-      subject)))
+  (if (string-match "^[Rr][Ee]: *" subject)
+      (substring subject (match-end 0))
+    subject))
+
+(defsubst gnus-functionp (form)
+  "Return non-nil if FORM is funcallable."
+  (or (and (symbolp form) (fboundp form))
+      (and (listp form) (eq (car form) 'lambda))))
 
 (defsubst gnus-goto-char (point)
   (and point (goto-char point)))
 
 (defmacro gnus-buffer-exists-p (buffer)
-  (` (and (, buffer)
-         (funcall (if (stringp (, buffer)) 'get-buffer 'buffer-name)
-                  (, buffer)))))
+  `(let ((buffer ,buffer))
+     (and buffer
+         (funcall (if (stringp buffer) 'get-buffer 'buffer-name)
+                  buffer))))
 
 (defmacro gnus-kill-buffer (buffer)
-  (` (if (gnus-buffer-exists-p (, buffer))
-        (kill-buffer (, buffer)))))
+  `(let ((buf ,buffer))
+     (if (gnus-buffer-exists-p buf)
+        (kill-buffer buf))))
 
 (defsubst gnus-point-at-bol ()
-  "Return point at the beginning of line."
+  "Return point at the beginning of the line."
   (let ((p (point)))
     (beginning-of-line)
     (prog1
@@ -1809,23 +2166,221 @@ Thank you for your help in stamping out bugs.
       (goto-char p))))
 
 (defsubst gnus-point-at-eol ()
-  "Return point at the beginning of line."
+  "Return point at the end of the line."
   (let ((p (point)))
     (end-of-line)
     (prog1
        (point)
       (goto-char p))))
 
+(defun gnus-alive-p ()
+  "Say whether Gnus is running or not."
+  (and gnus-group-buffer
+       (get-buffer gnus-group-buffer)))
+
 ;; Delete the current line (and the next N lines.);
 (defmacro gnus-delete-line (&optional n)
-  (` (delete-region (progn (beginning-of-line) (point))
-                   (progn (forward-line (, (or n 1))) (point)))))
+  `(delete-region (progn (beginning-of-line) (point))
+                 (progn (forward-line ,(or n 1)) (point))))
 
-;;; Load the compatability functions. 
+;; Suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
+(defvar gnus-init-inhibit nil)
+(defun gnus-read-init-file (&optional inhibit-next)
+  (if gnus-init-inhibit
+      (setq gnus-init-inhibit nil)
+    (setq gnus-init-inhibit inhibit-next)
+    (and gnus-init-file
+        (or (and (file-exists-p gnus-init-file)
+                 ;; Don't try to load a directory.
+                 (not (file-directory-p gnus-init-file)))
+            (file-exists-p (concat gnus-init-file ".el"))
+            (file-exists-p (concat gnus-init-file ".elc")))
+        (condition-case var
+            (load gnus-init-file nil t)
+          (error
+           (error "Error in %s: %s" gnus-init-file var))))))
+
+;; Info access macros.
+
+(defmacro gnus-info-group (info)
+  `(nth 0 ,info))
+(defmacro gnus-info-rank (info)
+  `(nth 1 ,info))
+(defmacro gnus-info-read (info)
+  `(nth 2 ,info))
+(defmacro gnus-info-marks (info)
+  `(nth 3 ,info))
+(defmacro gnus-info-method (info)
+  `(nth 4 ,info))
+(defmacro gnus-info-params (info)
+  `(nth 5 ,info))
+
+(defmacro gnus-info-level (info)
+  `(let ((rank (gnus-info-rank ,info)))
+     (if (consp rank)
+        (car rank)
+       rank)))
+(defmacro gnus-info-score (info)
+  `(let ((rank (gnus-info-rank ,info)))
+     (or (and (consp rank) (cdr rank)) 0)))
+
+(defmacro gnus-info-set-group (info group)
+  `(setcar ,info ,group))
+(defmacro gnus-info-set-rank (info rank)
+  `(setcar (nthcdr 1 ,info) ,rank))
+(defmacro gnus-info-set-read (info read)
+  `(setcar (nthcdr 2 ,info) ,read))
+(defmacro gnus-info-set-marks (info marks)
+  `(setcar (nthcdr 3 ,info) ,marks))
+(defmacro gnus-info-set-method (info method)
+  `(setcar (nthcdr 4 ,info) ,method))
+(defmacro gnus-info-set-params (info params)
+  `(setcar (nthcdr 5 ,info) ,params))
+
+(defmacro gnus-info-set-level (info level)
+  `(let ((rank (cdr ,info)))
+     (if (consp (car rank))
+        (setcar (car rank) ,level)
+       (setcar rank ,level))))
+(defmacro gnus-info-set-score (info score)
+  `(let ((rank (cdr ,info)))
+     (if (consp (car rank))
+        (setcdr (car rank) ,score)
+       (setcar rank (cons (car rank) ,score)))))
+
+(defmacro gnus-get-info (group)
+  `(nth 2 (gnus-gethash ,group gnus-newsrc-hashtb)))
+
+(defun gnus-byte-code (func)
+  "Return a form that can be `eval'ed based on FUNC."
+  (let ((fval (symbol-function func)))
+    (if (byte-code-function-p fval)
+       (let ((flist (append fval nil)))
+         (setcar flist 'byte-code)
+         flist)
+      (cons 'progn (cddr fval)))))
+
+;;; Load the compatability functions.
 
 (require 'gnus-cus)
 (require 'gnus-ems)
 
+\f
+;;;
+;;; Shutdown
+;;;
+
+(defvar gnus-shutdown-alist nil)
+
+(defun gnus-add-shutdown (function &rest symbols)
+  "Run FUNCTION whenever one of SYMBOLS is shut down."
+  (push (cons function symbols) gnus-shutdown-alist))
+
+(defun gnus-shutdown (symbol)
+  "Shut down everything that waits for SYMBOL."
+  (let ((alist gnus-shutdown-alist)
+       entry)
+    (while (setq entry (pop alist))
+      (when (memq symbol (cdr entry))
+       (funcall (car entry))))))
+
+\f
+
+;; Format specs.  The chunks below are the machine-generated forms
+;; that are to be evaled as the result of the default format strings.
+;; We write them in here to get them byte-compiled.  That way the
+;; default actions will be quite fast, while still retaining the full
+;; flexibility of the user-defined format specs.
+
+;; First we have lots of dummy defvars to let the compiler know these
+;; are really dynamic variables.
+
+(defvar gnus-tmp-unread)
+(defvar gnus-tmp-replied)
+(defvar gnus-tmp-score-char)
+(defvar gnus-tmp-indentation)
+(defvar gnus-tmp-opening-bracket)
+(defvar gnus-tmp-lines)
+(defvar gnus-tmp-name)
+(defvar gnus-tmp-closing-bracket)
+(defvar gnus-tmp-subject-or-nil)
+(defvar gnus-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)
+(defvar gnus-tmp-group-name)
+(defvar gnus-tmp-group)
+(defvar gnus-tmp-article-number)
+(defvar gnus-tmp-unread-and-unselected)
+(defvar gnus-tmp-news-method)
+(defvar gnus-tmp-news-server)
+(defvar gnus-tmp-article-number)
+(defvar gnus-mouse-face)
+(defvar gnus-mouse-face-prop)
+
+(defun gnus-summary-line-format-spec ()
+  (insert gnus-tmp-unread gnus-tmp-replied
+         gnus-tmp-score-char gnus-tmp-indentation)
+  (put-text-property
+   (point)
+   (progn
+     (insert
+      gnus-tmp-opening-bracket
+      (format "%4d: %-20s"
+             gnus-tmp-lines
+             (if (> (length gnus-tmp-name) 20)
+                 (substring gnus-tmp-name 0 20)
+               gnus-tmp-name))
+      gnus-tmp-closing-bracket)
+     (point))
+   gnus-mouse-face-prop gnus-mouse-face)
+  (insert " " gnus-tmp-subject-or-nil "\n"))
+
+(defvar gnus-summary-line-format-spec
+  (gnus-byte-code 'gnus-summary-line-format-spec))
+
+(defun gnus-summary-dummy-line-format-spec ()
+  (insert "*  ")
+  (put-text-property
+   (point)
+   (progn
+     (insert ":                                 :")
+     (point))
+   gnus-mouse-face-prop gnus-mouse-face)
+  (insert " " gnus-tmp-subject "\n"))
+
+(defvar gnus-summary-dummy-line-format-spec
+  (gnus-byte-code 'gnus-summary-dummy-line-format-spec))
+
+(defun gnus-group-line-format-spec ()
+  (insert gnus-tmp-marked-mark gnus-tmp-subscribed
+         gnus-tmp-process-marked
+         gnus-group-indentation
+         (format "%5s: " gnus-tmp-number-of-unread))
+  (put-text-property
+   (point)
+   (progn
+     (insert gnus-tmp-group "\n")
+     (1- (point)))
+   gnus-mouse-face-prop gnus-mouse-face))
+(defvar gnus-group-line-format-spec
+  (gnus-byte-code 'gnus-group-line-format-spec))
+
+(defvar gnus-format-specs
+  `((version . ,emacs-version)
+    (group ,gnus-group-line-format ,gnus-group-line-format-spec)
+    (summary-dummy ,gnus-summary-dummy-line-format
+                  ,gnus-summary-dummy-line-format-spec)
+    (summary ,gnus-summary-line-format ,gnus-summary-line-format-spec)))
+
+(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
 ;;;
 ;;; Gnus Utility Functions
@@ -1840,22 +2395,24 @@ Thank you for your help in stamping out bugs.
        (setq address (substring from (match-beginning 0) (match-end 0))))
     ;; Then we check whether the "name <address>" format is used.
     (and address
-        (string-match (concat "<" (regexp-quote address) ">") from)
-        (and (setq name (substring from 0 (1- (match-beginning 0))))
+        ;; Fix by MORIOKA Tomohiko <morioka@jaist.ac.jp>
+        ;; Linear white space is not required.
+        (string-match (concat "[ \t]*<" (regexp-quote address) ">") from)
+        (and (setq name (substring from 0 (match-beginning 0)))
              ;; Strip any quotes from the name.
              (string-match "\".*\"" name)
              (setq name (substring name 1 (1- (match-end 0))))))
     ;; If not, then "address (name)" is used.
     (or name
        (and (string-match "(.+)" from)
-            (setq name (substring from (1+ (match-beginning 0)) 
+            (setq name (substring from (1+ (match-beginning 0))
                                   (1- (match-end 0)))))
        (and (string-match "()" from)
             (setq name address))
        ;; Fix by MORIOKA Tomohiko <morioka@jaist.ac.jp>.
        ;; XOVER might not support folded From headers.
        (and (string-match "(.*" from)
-            (setq name (substring from (1+ (match-beginning 0)) 
+            (setq name (substring from (1+ (match-beginning 0))
                                   (match-end 0)))))
     ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
     (list (or name from) (or address from))))
@@ -1864,190 +2421,345 @@ Thank you for your help in stamping out bugs.
   "Return the value of the header FIELD of current article."
   (save-excursion
     (save-restriction
-      (let ((case-fold-search t))
-       (gnus-narrow-to-headers)
+      (let ((case-fold-search t)
+           (inhibit-point-motion-hooks t))
+       (nnheader-narrow-to-headers)
        (mail-fetch-field field)))))
 
 (defun gnus-goto-colon ()
   (beginning-of-line)
   (search-forward ":" (gnus-point-at-eol) t))
 
-(defun gnus-narrow-to-headers ()
-  (widen)
-  (save-excursion
-    (narrow-to-region
-     (goto-char (point-min))
-     (if (search-forward "\n\n" nil t)
-        (1- (point))
-       (point-max)))))
-
-(defvar gnus-old-specs nil)
+;;;###autoload
+(defun gnus-update-format (var)
+  "Update the format specification near point."
+  (interactive
+   (list
+    (save-excursion
+      (eval-defun nil)
+      ;; Find the end of the current word.
+      (re-search-forward "[ \t\n]" nil t)
+      ;; Search backward.
+      (when (re-search-backward "\\(gnus-[-a-z]+-line-format\\)" nil t)
+       (match-string 1)))))
+  (let* ((type (intern (progn (string-match "gnus-\\([-a-z]+\\)-line" var)
+                             (match-string 1 var))))
+        (entry (assq type gnus-format-specs))
+        value spec)
+    (when entry
+      (setq gnus-format-specs (delq entry gnus-format-specs)))
+    (set
+     (intern (format "%s-spec" var))
+     (gnus-parse-format (setq value (symbol-value (intern var)))
+                       (symbol-value (intern (format "%s-alist" var)))
+                       (not (string-match "mode" var))))
+    (setq spec (symbol-value (intern (format "%s-spec" var))))
+    (push (list type value spec) gnus-format-specs)
+
+    (pop-to-buffer "*Gnus Format*")
+    (erase-buffer)
+    (lisp-interaction-mode)
+    (insert (pp-to-string spec))))
 
-(defun gnus-update-format-specifications ()
+(defun gnus-update-format-specifications (&optional force)
+  "Update all (necessary) format specifications."
+  ;; Make the indentation array.
   (gnus-make-thread-indent-array)
 
-  (let ((formats '(summary summary-dummy group 
-                          summary-mode group-mode article-mode))
-       old-format new-format)
-    (while formats
-      (setq new-format (symbol-value
-                       (intern (format "gnus-%s-line-format" (car formats)))))
-      (or (and (setq old-format (cdr (assq (car formats) gnus-old-specs)))
-              (equal old-format new-format))
-         (set (intern (format "gnus-%s-line-format-spec" (car formats)))
-              (gnus-parse-format
-               new-format
-               (symbol-value 
-                (intern (format "gnus-%s-line-format-alist"
-                                (if (eq (car formats) 'article-mode)
-                                    'summary-mode (car formats))))))))
-      (setq gnus-old-specs (cons (cons (car formats) new-format)
-                                (delq (car formats) gnus-old-specs)))
-      (setq formats (cdr formats))))
-      
-  (gnus-update-group-mark-positions)
-  (gnus-update-summary-mark-positions)
+  ;; See whether all the stored info needs to be flushed.
+  (when (or force
+           (not (equal emacs-version
+                       (cdr (assq 'version gnus-format-specs)))))
+    (setq gnus-format-specs nil))
+
+  ;; Go through all the formats and see whether they need updating.
+  (let ((types '(summary summary-dummy group
+                        summary-mode group-mode article-mode))
+       new-format entry type val)
+    (while (setq type (pop types))
+      ;; Jump to the proper buffer to find out the value of
+      ;; the variable, if possible.  (It may be buffer-local.)
+      (save-excursion
+       (let ((buffer (intern (format "gnus-%s-buffer" type)))
+             val)
+         (when (and (boundp buffer)
+                    (setq val (symbol-value buffer))
+                    (get-buffer val)
+                    (buffer-name (get-buffer val)))
+           (set-buffer (get-buffer val)))
+         (setq new-format (symbol-value
+                           (intern (format "gnus-%s-line-format" type))))))
+      (setq entry (cdr (assq type gnus-format-specs)))
+      (if (and entry
+              (equal (car entry) new-format))
+         ;; Use the old format.
+         (set (intern (format "gnus-%s-line-format-spec" type))
+              (cadr entry))
+       ;; This is a new format.
+       (setq val
+             (if (not (stringp new-format))
+                 ;; This is a function call or something.
+                 new-format
+               ;; This is a "real" format.
+               (gnus-parse-format
+                new-format
+                (symbol-value
+                 (intern (format "gnus-%s-line-format-alist"
+                                 (if (eq type 'article-mode)
+                                     'summary-mode type))))
+                (not (string-match "mode$" (symbol-name type))))))
+       ;; Enter the new format spec into the list.
+       (if entry
+           (progn
+             (setcar (cdr entry) val)
+             (setcar entry new-format))
+         (push (list type new-format val) gnus-format-specs))
+       (set (intern (format "gnus-%s-line-format-spec" type)) val))))
 
-  (if (and (string-match "%D" gnus-group-line-format)
-          (not gnus-description-hashtb)
-          gnus-read-active-file)
-      (gnus-read-all-descriptions-files)))
+  (unless (assq 'version gnus-format-specs)
+    (push (cons 'version emacs-version) gnus-format-specs))
+
+  (gnus-update-group-mark-positions)
+  (gnus-update-summary-mark-positions))
 
 (defun gnus-update-summary-mark-positions ()
+  "Compute where the summary marks are to go."
   (save-excursion
     (let ((gnus-replied-mark 129)
          (gnus-score-below-mark 130)
          (gnus-score-over-mark 130)
          (thread nil)
+         (gnus-visual nil)
          pos)
       (gnus-set-work-buffer)
-      (gnus-summary-insert-line 
-       nil [0 "" "" "" "" "" 0 0 ""]  0 nil 128 t nil "" nil 1)
+      (gnus-summary-insert-line
+       [0 "" "" "" "" "" 0 0 ""]  0 nil 128 t nil "" nil 1)
       (goto-char (point-min))
       (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
                                         (- (point) 2)))))
       (goto-char (point-min))
-      (setq pos (cons (cons 'replied (and (search-forward "\201" nil t)
-                                         (- (point) 2))) pos))
+      (push (cons 'replied (and (search-forward "\201" nil t) (- (point) 2)))
+           pos)
       (goto-char (point-min))
-      (setq pos (cons (cons 'score (and (search-forward "\202" nil t)
-                                       (- (point) 2))) pos))
+      (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
+           pos)
       (setq gnus-summary-mark-positions pos))))
 
 (defun gnus-update-group-mark-positions ()
   (save-excursion
     (let ((gnus-process-mark 128)
          (gnus-group-marked '("dummy.group")))
-      (gnus-sethash "dummy.group" '(0 . 0) gnus-active-hashtb)
+      (gnus-set-active "dummy.group" '(0 . 0))
       (gnus-set-work-buffer)
-      (gnus-group-insert-group-line nil "dummy.group" 0 nil 0 nil)
+      (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
       (goto-char (point-min))
       (setq gnus-group-mark-positions
            (list (cons 'process (and (search-forward "\200" nil t)
                                      (- (point) 2))))))))
 
-(defun gnus-mouse-face-function (form)
-  (` (let ((string (, form)))
-       (put-text-property 0 (length string) 'mouse-face gnus-mouse-face string)
-       string)))
+(defvar gnus-mouse-face-0 'highlight)
+(defvar gnus-mouse-face-1 'highlight)
+(defvar gnus-mouse-face-2 'highlight)
+(defvar gnus-mouse-face-3 'highlight)
+(defvar gnus-mouse-face-4 'highlight)
+
+(defun gnus-mouse-face-function (form type)
+  `(put-text-property
+    (point) (progn ,@form (point))
+    gnus-mouse-face-prop
+    ,(if (equal type 0)
+        'gnus-mouse-face
+       `(quote ,(symbol-value (intern (format "gnus-mouse-face-%d" type)))))))
+
+(defvar gnus-face-0 'bold)
+(defvar gnus-face-1 'italic)
+(defvar gnus-face-2 'bold-italic)
+(defvar gnus-face-3 'bold)
+(defvar gnus-face-4 'bold)
+
+(defun gnus-face-face-function (form type)
+  `(put-text-property
+    (point) (progn ,@form (point))
+    'face ',(symbol-value (intern (format "gnus-face-%d" type)))))
 
 (defun gnus-max-width-function (el max-width)
   (or (numberp max-width) (signal 'wrong-type-argument '(numberp max-width)))
-  (` (let* ((val (eval (, el)))
-           (valstr (if (numberp val)
-                       (int-to-string val) val)))
-       (if (> (length valstr) (, max-width))
-          (substring valstr 0 (, max-width))
-        valstr))))
-
-(defun gnus-parse-format (format spec-alist)
+  (if (symbolp el)
+      `(if (> (length ,el) ,max-width)
+          (substring ,el 0 ,max-width)
+        ,el)
+    `(let ((val (eval ,el)))
+       (if (numberp val)
+          (setq val (int-to-string val)))
+       (if (> (length val) ,max-width)
+          (substring val 0 ,max-width)
+        val))))
+
+(defun gnus-parse-format (format spec-alist &optional insert)
   ;; This function parses the FORMAT string with the help of the
   ;; SPEC-ALIST and returns a list that can be eval'ed to return the
   ;; string.  If the FORMAT string contains the specifiers %( and %)
   ;; the text between them will have the mouse-face text property.
-  (if (string-match "\\`\\(.*\\)%(\\(.*\\)%)\\(.*\n?\\)\\'" format)
-      (if (and gnus-visual gnus-mouse-face)
-         (let ((pre (substring format (match-beginning 1) (match-end 1)))
-               (button (substring format (match-beginning 2) (match-end 2)))
-               (post (substring format (match-beginning 3) (match-end 3))))
-           (list 'concat
-                 (gnus-parse-simple-format pre spec-alist)
-                 (gnus-mouse-face-function 
-                  (gnus-parse-simple-format button spec-alist))
-                 (gnus-parse-simple-format post spec-alist)))
-       (gnus-parse-simple-format
-        (concat (substring format (match-beginning 1) (match-end 1))
-                (substring format (match-beginning 2) (match-end 2))
-                (substring format (match-beginning 3) (match-end 3)))
-        spec-alist))
-    (gnus-parse-simple-format format spec-alist)))
-
-(defun gnus-parse-simple-format (format spec-alist)
+  (if (string-match
+       "\\`\\(.*\\)%[0-9]?[{(]\\(.*\\)%[0-9]?[})]\\(.*\n?\\)\\'"
+       format)
+      (gnus-parse-complex-format format spec-alist)
+    ;; This is a simple format.
+    (gnus-parse-simple-format format spec-alist insert)))
+
+(defun gnus-parse-complex-format (format spec-alist)
+  (save-excursion
+    (gnus-set-work-buffer)
+    (insert format)
+    (goto-char (point-min))
+    (while (re-search-forward "\"" nil t)
+      (replace-match "\\\"" nil t))
+    (goto-char (point-min))
+    (insert "(\"")
+    (while (re-search-forward "%\\([0-9]+\\)?\\([{}()]\\)" nil t)
+      (let ((number (if (match-beginning 1)
+                       (match-string 1) "0"))
+           (delim (aref (match-string 2) 0)))
+       (if (or (= delim ?\() (= delim ?\{))
+           (replace-match (concat "\"(" (if (= delim ?\() "mouse" "face")
+                                  " " number " \""))
+         (replace-match "\")\""))))
+    (goto-char (point-max))
+    (insert "\")")
+    (goto-char (point-min))
+    (let ((form (read (current-buffer))))
+      (cons 'progn (gnus-complex-form-to-spec form spec-alist)))))
+
+(defun gnus-complex-form-to-spec (form spec-alist)
+  (delq nil
+       (mapcar
+        (lambda (sform)
+          (if (stringp sform)
+              (gnus-parse-simple-format sform spec-alist t)
+            (funcall (intern (format "gnus-%s-face-function" (car sform)))
+                     (gnus-complex-form-to-spec (cddr sform) spec-alist)
+                     (nth 1 sform))))
+        form)))
+
+(defun gnus-parse-simple-format (format spec-alist &optional insert)
   ;; This function parses the FORMAT string with the help of the
-  ;; SPEC-ALIST and returns a list that can be eval'ed to return the
-  ;; string. The list will consist of the symbol `format', a format
-  ;; specification string, and a list of forms depending on the
-  ;; SPEC-ALIST.
+  ;; SPEC-ALIST and returns a list that can be eval'ed to return a
+  ;; string.
   (let ((max-width 0)
-       spec flist fstring newspec elem beg)
+       spec flist fstring newspec elem beg result dontinsert)
     (save-excursion
       (gnus-set-work-buffer)
       (insert format)
       (goto-char (point-min))
-      (while (re-search-forward "%[-0-9]*\\(,[0-9]*\\)*\\(.\\)\\(.\\)?" nil t)
-       (setq spec (string-to-char (buffer-substring (match-beginning 2)
-                                                    (match-end 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'.
-       (if (not (setq elem (cdr (assq spec spec-alist))))
+      (while (re-search-forward "%[-0-9]*\\(,[0-9]+\\)?\\([^0-9]\\)\\(.\\)?"
+                               nil t)
+       (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
-       (and (eq (car elem) 'user-defined)
-            (setq elem
-                  (list 
-                   (list (intern (concat "gnus-user-format-function-"
-                                         (buffer-substring
-                                          (match-beginning 3)
-                                          (match-end 3))))
-                         '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))))
+         ;; 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 ((= (cadr elem) ?c)
+                      (setq el (list 'char-to-string el)))
+                     ((= (cadr elem) ?d)
+                      (setq el (list 'int-to-string el))))
+               (setq flist (cons (gnus-max-width-function el max-width)
+                                 flist))
+               (setq newspec ?s))
+           (progn
+             (setq flist (cons (car elem) flist))
+             (setq newspec (cadr elem)))))
        ;; Remove the old specification (and possibly a ",12" string).
        (delete-region beg (match-end 2))
        ;; Insert the new specification.
        (goto-char beg)
        (insert newspec))
       (setq fstring (buffer-substring 1 (point-max))))
-    (cons 'format (cons fstring (nreverse flist)))))
-
-;; Suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
-(defun gnus-read-init-file ()
-  (and gnus-init-file
-       (or (and (file-exists-p gnus-init-file) 
-               ;; Don't try to load a directory.
-               (not (file-directory-p gnus-init-file)))
-          (file-exists-p (concat gnus-init-file ".el"))
-          (file-exists-p (concat gnus-init-file ".elc")))
-       (load gnus-init-file nil t)))
+    ;; Do some postprocessing to increase efficiency.
+    (setq
+     result
+     (cond
+      ;; Emptyness.
+      ((string= fstring "")
+       nil)
+      ;; Not a format string.
+      ((not (string-match "%" fstring))
+       (list fstring))
+      ;; A format string with just a single string spec.
+      ((string= fstring "%s")
+       (list (car flist)))
+      ;; A single character.
+      ((string= fstring "%c")
+       (list (car flist)))
+      ;; A single number.
+      ((string= fstring "%d")
+       (setq dontinsert)
+       (if insert
+          (list `(princ ,(car flist)))
+        (list `(int-to-string ,(car flist)))))
+      ;; Just lots of chars and strings.
+      ((string-match "\\`\\(%[cs]\\)+\\'" fstring)
+       (nreverse flist))
+      ;; A single string spec at the beginning of the spec.
+      ((string-match "\\`%[sc][^%]+\\'" fstring)
+       (list (car flist) (substring fstring 2)))
+      ;; A single string spec in the middle of the spec.
+      ((string-match "\\`\\([^%]+\\)%[sc]\\([^%]+\\)\\'" fstring)
+       (list (match-string 1 fstring) (car flist) (match-string 2 fstring)))
+      ;; A single string spec in the end of the spec.
+      ((string-match "\\`\\([^%]+\\)%[sc]\\'" fstring)
+       (list (match-string 1 fstring) (car flist)))
+      ;; A more complex spec.
+      (t
+       (list (cons 'format (cons fstring (nreverse flist)))))))
+
+    (if insert
+       (when result
+         (if dontinsert
+             result
+           (cons 'insert result)))
+      (cond ((stringp result)
+            result)
+           ((consp result)
+            (cons 'concat result))
+           (t "")))))
+
+(defun gnus-eval-format (format &optional alist props)
+  "Eval the format variable FORMAT, using ALIST.
+If PROPS, 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))
+      (while (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)
@@ -2070,7 +2782,7 @@ Otherwise, it is like ~/News/news/group/num."
           (concat (if (gnus-use-long-file-name 'not-save)
                       (gnus-capitalize-newsgroup newsgroup)
                     (gnus-newsgroup-directory-form newsgroup))
-                  "/" (int-to-string (header-number headers)))
+                  "/" (int-to-string (mail-header-number headers)))
           (or gnus-article-save-directory "~/News"))))
     (if (and last-file
             (string-equal (file-name-directory default)
@@ -2082,13 +2794,13 @@ Otherwise, it is like ~/News/news/group/num."
 (defun gnus-numeric-save-name (newsgroup headers &optional last-file)
   "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
 If variable `gnus-use-long-file-name' is non-nil, it is
-~/News/news.group/num.  Otherwise, it is like ~/News/news/group/num."
+~/News/news.group/num. Otherwise, it is like ~/News/news/group/num."
   (let ((default
          (expand-file-name
           (concat (if (gnus-use-long-file-name 'not-save)
                       newsgroup
                     (gnus-newsgroup-directory-form newsgroup))
-                  "/" (int-to-string (header-number headers)))
+                  "/" (int-to-string (mail-header-number headers)))
           (or gnus-article-save-directory "~/News"))))
     (if (and last-file
             (string-equal (file-name-directory default)
@@ -2133,26 +2845,26 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        (setq start (1- (length prefix)))
        (if (and (string-match "[^\\.]\\." (car groups) start)
                 (cdr groups)
-                (setq prefix 
+                (setq prefix
                       (concat "^" (substring (car groups) 0 (match-end 0))))
-                (string-match prefix (car (cdr groups))))
+                (string-match prefix (cadr groups)))
            (progn
              (setq prefixes (cons prefix prefixes))
-             (message "Descend hierarchy %s? ([y]nsq): " 
+             (message "Descend hierarchy %s? ([y]nsq): "
                       (substring prefix 1 (1- (length prefix))))
              (setq ans (read-char))
              (cond ((= ans ?n)
-                    (while (and groups 
-                                (string-match prefix 
+                    (while (and groups
+                                (string-match prefix
                                               (setq group (car groups))))
-                      (setq gnus-killed-list 
+                      (setq gnus-killed-list
                             (cons group gnus-killed-list))
                       (gnus-sethash group group gnus-killed-hashtb)
                       (setq groups (cdr groups)))
                     (setq starts (cdr starts)))
                    ((= ans ?s)
-                    (while (and groups 
-                                (string-match prefix 
+                    (while (and groups
+                                (string-match prefix
                                               (setq group (car groups))))
                       (gnus-sethash group group gnus-killed-hashtb)
                       (gnus-subscribe-alphabetically (car groups))
@@ -2177,7 +2889,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                   (setq gnus-killed-list (cons group gnus-killed-list))
                   (gnus-sethash group group gnus-killed-hashtb)
                   (setq groups (cdr groups))))
-               (t 
+               (t
                 (setq gnus-killed-list (cons group gnus-killed-list))
                 (gnus-sethash group group gnus-killed-hashtb)))
          (setq groups (cdr groups)))))))
@@ -2188,12 +2900,11 @@ If variable `gnus-use-long-file-name' is non-nil, it is
 
 (defun gnus-subscribe-alphabetically (newgroup)
   "Subscribe new NEWSGROUP and insert it in alphabetical order."
-  ;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
   (let ((groups (cdr gnus-newsrc-alist))
        before)
     (while (and (not before) groups)
-      (if (string< newgroup (car (car groups)))
-         (setq before (car (car groups)))
+      (if (string< newgroup (caar groups))
+         (setq before (caar groups))
        (setq groups (cdr groups))))
     (gnus-subscribe-newsgroup newgroup before)))
 
@@ -2210,8 +2921,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
               (concat "^\\(" (regexp-quote groupkey) ".*\\)[!:]")))
          (while (and (re-search-forward groupkey-re nil t)
                      (progn
-                       (setq before (buffer-substring
-                                     (match-beginning 1) (match-end 1)))
+                       (setq before (match-string 1))
                        (string< before newgroup)))))
        ;; Remove tail of newsgroup name (eg. a.b.c -> a.b)
        (setq groupkey
@@ -2219,24 +2929,28 @@ 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.
-It is inserted in hierarchical newsgroup order if subscribed. If not,
+(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.
-If NEXT is non-nil, it is inserted before NEXT. Otherwise it is made
+If NEXT is non-nil, it is inserted before NEXT.         Otherwise it is made
 the first newsgroup."
   ;; We subscribe the group by changing its level to `subscribed'.
-  (gnus-group-change-level 
+  (gnus-group-change-level
    newsgroup gnus-level-default-subscribed
    gnus-level-killed (gnus-gethash (or next "dummy.group") gnus-newsrc-hashtb))
   (gnus-message 5 "Subscribe newsgroup: %s" newsgroup))
@@ -2245,11 +2959,11 @@ the first newsgroup."
 
 (defun gnus-newsgroup-directory-form (newsgroup)
   "Make hierarchical directory name from NEWSGROUP name."
-  (let ((newsgroup (gnus-newsgroup-saveable-name newsgroup))
+  (let ((newsgroup (gnus-newsgroup-savable-name newsgroup))
        (len (length newsgroup))
        idx)
     ;; If this is a foreign group, we don't want to translate the
-    ;; entire name.  
+    ;; entire name.
     (if (setq idx (string-match ":" newsgroup))
        (aset newsgroup idx ?/)
       (setq idx 0))
@@ -2260,16 +2974,16 @@ the first newsgroup."
       (setq idx (1+ idx)))
     newsgroup))
 
-(defun gnus-newsgroup-saveable-name (group)
+(defun gnus-newsgroup-savable-name (group)
   ;; Replace any slashes in a group name (eg. an ange-ftp nndoc group)
   ;; with dots.
-  (gnus-replace-chars-in-string group ?/ ?.))
+  (nnheader-replace-chars-in-string group ?/ ?.))
 
 (defun gnus-make-directory (dir)
   "Make DIRECTORY recursively."
-  ;; Why don't we use `(make-directory dir 'parents)'? That's just one
+  ;; Why don't we use `(make-directory dir 'parents)'?  That's just one
   ;; of the many mysteries of the universe.
- (let* ((dir (expand-file-name dir default-directory))
 (let* ((dir (expand-file-name dir default-directory))
         dirs err)
     (if (string-match "/$" dir)
        (setq dir (substring dir 0 (match-beginning 0))))
@@ -2284,7 +2998,7 @@ the first newsgroup."
          (make-directory (car dirs))
        (error (setq err t)))
       (setq dirs (cdr dirs)))
-    ;; We return whether we were successful or not. 
+    ;; We return whether we were successful or not.
     (not dirs)))
 
 (defun gnus-capitalize-newsgroup (newsgroup)
@@ -2293,55 +3007,85 @@ the first newsgroup."
        (concat (char-to-string (upcase (aref newsgroup 0)))
               (substring newsgroup 1))))
 
-;; Var
+;; Various... things.
 
 (defun gnus-simplify-subject (subject &optional re-only)
   "Remove `Re:' and words in parentheses.
-If optional argument RE-ONLY is non-nil, strip `Re:' only."
+If RE-ONLY is non-nil, strip leading `Re:'s only."
   (let ((case-fold-search t))          ;Ignore case.
-    ;; Remove `Re:' and `Re^N:'.
-    (if (string-match "^re:[ \t]*" subject)
+    ;; Remove `Re:', `Re^N:', `Re(n)', and `Re[n]:'.
+    (when (string-match "\\`\\(re\\([[(^][0-9]+[])]?\\)?:[ \t]*\\)+" subject)
+      (setq subject (substring subject (match-end 0))))
+    ;; Remove uninteresting prefixes.
+    (if (and (not re-only)
+            gnus-simplify-ignored-prefixes
+            (string-match gnus-simplify-ignored-prefixes subject))
        (setq subject (substring subject (match-end 0))))
     ;; Remove words in parentheses from end.
-    (or re-only
-       (while (string-match "[ \t\n]*([^()]*)[ \t\n]*\\'" subject)
-         (setq subject (substring subject 0 (match-beginning 0)))))
+    (unless re-only
+      (while (string-match "[ \t\n]*([^()]*)[ \t\n]*\\'" subject)
+       (setq subject (substring subject 0 (match-beginning 0)))))
     ;; Return subject string.
     subject))
 
 ;; Remove any leading "re:"s, any trailing paren phrases, and simplify
 ;; all whitespace.
-(defun gnus-simplify-subject-fuzzy (subject)
-  (let ((case-fold-search t))
-    (save-excursion
-      (gnus-set-work-buffer)
-      (insert subject)
-      (inline (gnus-simplify-buffer-fuzzy))
-      (buffer-string))))
-
+;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
 (defun gnus-simplify-buffer-fuzzy ()
   (goto-char (point-min))
-  ;; Fix by Stainless Steel Rat <ratinox@ccs.neu.edu>.
-  (while (re-search-forward "^[ \t]*\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;][ \t]*"
-                           nil t)
-    (replace-match "" t t))
+  (while (search-forward "\t" nil t)
+    (replace-match " " t t))
+  (goto-char (point-min))
+  (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *" nil t)
+  (goto-char (match-beginning 0))
+  (while (or
+         (looking-at "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
+         (looking-at "^[[].*: .*[]]$"))
+    (goto-char (point-min))
+    (while (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
+                             nil t)
+      (replace-match "" t t))
+    (goto-char (point-min))
+    (while (re-search-forward "^[[].*: .*[]]$" nil t)
+      (goto-char (match-end 0))
+      (delete-char -1)
+      (delete-region
+       (progn (goto-char (match-beginning 0)))
+       (re-search-forward ":"))))
   (goto-char (point-min))
-  (while (re-search-forward "[ \t\n]*([^()]*)[ \t\n]*$" nil t)
+  (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
     (replace-match "" t t))
   (goto-char (point-min))
-  (while (re-search-forward "[ \t]+" nil t)
+  (while (re-search-forward "  +" nil t)
     (replace-match " " t t))
   (goto-char (point-min))
-  (while (re-search-forward "[ \t]+$" nil t)
+  (while (re-search-forward " $" nil t)
     (replace-match "" t t))
   (goto-char (point-min))
-  (while (re-search-forward "^[ \t]+" nil t)
+  (while (re-search-forward "^ +" nil t)
     (replace-match "" t t))
-  (if gnus-simplify-subject-fuzzy-regexp
+  (goto-char (point-min))
+  (when gnus-simplify-subject-fuzzy-regexp
+    (if (listp gnus-simplify-subject-fuzzy-regexp)
+       (let ((list gnus-simplify-subject-fuzzy-regexp))
+         (while list
+           (goto-char (point-min))
+           (while (re-search-forward (car list) nil t)
+             (replace-match "" t t))
+           (setq list (cdr list))))
       (while (re-search-forward gnus-simplify-subject-fuzzy-regexp nil t)
-       (replace-match "" t t))))
+       (replace-match "" t t)))))
+
+(defun gnus-simplify-subject-fuzzy (subject)
+  "Siplify a subject string fuzzily."
+  (save-excursion
+    (gnus-set-work-buffer)
+    (let ((case-fold-search t))
+      (insert subject)
+      (inline (gnus-simplify-buffer-fuzzy))
+      (buffer-string))))
 
-;; Add the current buffer to the list of buffers to be killed on exit. 
+;; Add the current buffer to&n