*** empty log message ***
[gnus] / lisp / gnus.el
index 30938d8..31c5e1c 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:
 
 (require 'mail-utils)
 (require 'timezone)
 (require 'nnheader)
+(require 'message)
+(require 'nnmail)
+(require 'backquote)
 
 (eval-when-compile (require 'cl))
 
+(defvar gnus-directory (or (getenv "SAVEDIR") "~/News/")
+  "*Directory variable from which all other Gnus file variables are derived.")
+
 ;; Site dependent variables.  These variables should be defined in
 ;; paths.el.
 
@@ -43,7 +50,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.")
@@ -65,17 +72,6 @@ In any case, if the string (either in the variable, in the environment
 variable, or returned by the function) is a file name, the contents of
 this file will be used as the organization.")
 
-(defvar gnus-use-generic-from nil
-  "If nil, the full host name will be the system name prepended to the domain name.
-If this is a string, the full host name will be this string.
-If this is non-nil, non-string, the domain name will be used as the
-full host name.")
-
-(defvar gnus-use-generic-path nil
-  "If nil, use the NNTP server name in the Path header.
-If stringp, use this; if non-nil, use no host name (user name only).")
-
-
 ;; Customization variables
 
 ;; Don't touch this variable.
@@ -106,8 +102,8 @@ used to 899, you would say something along these lines:
                       nil
                     name)
                 (kill-buffer (current-buffer))))))))
-                
-(defvar gnus-select-method 
+
+(defvar gnus-select-method
   (nconc
    (list 'nntp (or (condition-case ()
                       (gnus-getenv-nntpserver)
@@ -118,11 +114,11 @@ used to 899, you would say something along these lines:
                   (system-name)))
    (if (or (null gnus-nntp-service)
           (equal gnus-nntp-service "nntp"))
-       nil 
+       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:
@@ -138,16 +134,20 @@ 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 ,(nnheader-concat message-directory "archive"))
+    (nnfolder-active-file 
+     ,(nnheader-concat message-directory "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.
+
+It's probably not a very effective to change this variable once you've
+run Gnus once.  After doing that, you must edit this server from the
+server buffer.")
 
 (defvar gnus-refer-article-method nil
   "*Preferred method for fetching an article by Message-ID.
@@ -156,12 +156,12 @@ 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:
@@ -175,7 +175,7 @@ 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-startup-file "~/.newsrc"
@@ -185,18 +185,19 @@ variable instead.")
 (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@ftp.uu.net:/usenet/news.answers/"
+    "/ftp@sunsite.auc.dk:/pub/usenet/"
+    "/ftp@sunsite.doc.ic.ac.uk:/pub/usenet/news-faqs/"
+    "/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
     "/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
-    "/ftp@rtfm.mit.edu:/pub/usenet/news.answers/"
+    "/ftp@rtfm.mit.edu:/pub/usenet/"
     "/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
-;    "/ftp@ftp.Germany.EU.net:/pub/newsarchive/news.answers/"
     "/ftp@ftp.sunet.se:/pub/usenet/"
     "/ftp@nctuccca.edu.tw:/USENET/FAQ/"
-    "/ftp@hwarang.postech.ac.kr:/pub/usenet/news.answers/"
+    "/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
@@ -212,17 +213,19 @@ something of value back from them.
 
 If the default site is too slow, try one of these:
 
-   North America: 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.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
@@ -238,8 +241,12 @@ 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.
@@ -276,15 +283,17 @@ If this variable is a list, and the list contains the element
 `not-score', long file names will not be used for score files; if it
 contains the element `not-save', long file names will not be used for
 saving; and if it contains the element `not-kill', long file names
-will not be used for kill files.")
+will not be used for kill files.
 
-(defvar gnus-article-save-directory (or (getenv "SAVEDIR") "~/News/")
-  "*Name of the directory articles will be saved in (default \"~/News\").
-Initialized from the SAVEDIR environment variable.")
+Note that the default for this variable varies according to what system
+type you're using.  On `usg-unix-v' and `xenix' this variable defaults
+to nil while on all other systems it defaults to t.")
 
-(defvar gnus-kill-files-directory (or (getenv "SAVEDIR") "~/News/")
-  "*Name of the directory where kill files will be stored (default \"~/News\").
-Initialized from the SAVEDIR environment variable.")
+(defvar gnus-article-save-directory gnus-directory
+  "*Name of the directory articles will be saved in (default \"~/News\").")
+
+(defvar gnus-kill-files-directory gnus-directory
+  "*Name of the directory where kill files will be stored (default \"~/News\").")
 
 (defvar gnus-default-article-saver 'gnus-summary-save-in-rmail
   "*A function to save articles in your favorite format.
@@ -325,7 +334,7 @@ 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 
+(defvar gnus-split-methods
   '((gnus-article-archive-name))
   "*Variable used to suggest where articles are to be saved.
 For instance, if you would like to save articles related to Gnus in
@@ -339,7 +348,7 @@ 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  
+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.
 
@@ -347,18 +356,28 @@ 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.")
 
 (defvar gnus-use-adaptive-scoring nil
   "*If non-nil, use some adaptive scoring scheme.")
 
-(defvar gnus-use-cache nil
+(defvar gnus-use-cache 'passive
   "*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
@@ -374,7 +393,7 @@ articles.  This is not a good idea.")
 (defvar gnus-use-scoring t
   "*If non-nil, enable scoring.")
 
-(defvar gnus-use-picon nil
+(defvar gnus-use-picons nil
   "*If non-nil, display picons.")
 
 (defvar gnus-fetch-old-headers nil
@@ -383,10 +402,10 @@ 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. 
+number of old headers will be fetched.
 
 The server has to support NOV for any of this to work.")
 
@@ -418,7 +437,7 @@ jabbering all the time.")
 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
 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
@@ -431,7 +450,7 @@ with the best level.")
 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. 
+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.
@@ -446,7 +465,7 @@ 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)$"
@@ -466,6 +485,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.
@@ -473,25 +508,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].")
@@ -546,7 +586,7 @@ you have many groups that you aren't interested in.")
 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 
+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
@@ -564,19 +604,17 @@ 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.")
 
-(defvar gnus-interactive-post t
-  "*If non-nil, group name will be asked for when posting.")
-
 (defvar gnus-interactive-exit t
   "*If non-nil, require your confirmation when exiting Gnus.")
 
@@ -613,21 +651,28 @@ simplification is selected.")
 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.")
+  "*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.")
@@ -635,7 +680,7 @@ 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.")
 
@@ -656,7 +701,7 @@ 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'.  
+`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
@@ -666,13 +711,13 @@ 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,
@@ -684,19 +729,25 @@ thus making them effectively non-existent.")
 This variable can also be a list of regexps of headers to be ignored.
 If `gnus-visible-headers' is non-nil, this variable will be ignored.")
 
-(defvar gnus-visible-headers "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Resent-"
+(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.")
 
@@ -715,6 +766,14 @@ will be kept while the rest will be deleted before saving.")
 (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.")
 
@@ -726,17 +785,19 @@ 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 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.")
+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.")
@@ -747,7 +808,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.
@@ -765,49 +828,61 @@ 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
-     (vertical 1.0 
-              (group 1.0 point) 
-              (if gnus-carpal (group-carpal 4))))
+     (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))))
+              (if gnus-carpal '(summary-carpal 4))))
     (article
-     (if gnus-use-picon
-        '(frame 1.0
-                (vertical 1.0
-                          (summary 0.25 point)
-                          (if gnus-carpal (summary-carpal 4)) 
-                          (article 1.0))
-                (vertical 1.0
-                          (picon 1.0)))
+     (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)) 
-                (article 1.0))))
+                (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))))
+              (if gnus-carpal '(server-carpal 2))))
     (browse
      (vertical 1.0
               (browse 1.0 point)
-              (if gnus-carpal (browse-carpal 2))))
-    (group-mail
+              (if gnus-carpal '(browse-carpal 2))))
+    (message
      (vertical 1.0
-              (mail 1.0 point)))
-    (summary-mail
+              (message 1.0 point)))
+    (pick
      (vertical 1.0
-              (mail 1.0 point)))
-    (summary-reply
-     (vertical 1.0
-              (article 0.5)
-              (mail 1.0 point)))
+              (article 1.0 point)))
     (info
      (vertical 1.0
-              (nil 1.0 point)))
+              (info 1.0 point)))
     (summary-faq
      (vertical 1.0
               (summary 0.25)
@@ -829,45 +904,43 @@ beginning of a line.")
               (post 1.0 point)))
     (reply
      (vertical 1.0
-              (article 0.5)
-              (mail 1.0 point)))
-    (mail-forward
-     (vertical 1.0
-              (mail 1.0 point)))
-    (post-forward
+              (article-copy 0.5)
+              (message 1.0 point)))
+    (forward
      (vertical 1.0
-              (post 1.0 point)))
+              (message 1.0 point)))
     (reply-yank
      (vertical 1.0
-              (mail 1.0 point)))
+              (message 1.0 point)))
     (mail-bounce
      (vertical 1.0
               (article 0.5)
-              (mail 1.0 point)))
+              (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)) 
+              (summary 0.25 point)
+              (if gnus-carpal '(summary-carpal 4))
               ("*Shell Command Output*" 1.0)))
-    (followup
+    (bug
      (vertical 1.0
-              (article 0.5)
-              (post 1.0 point)))
-    (followup-yank
+              ("*Gnus Help Bug*" 0.5)
+              ("*Gnus Bug*" 1.0 point)))
+    (compose-bounce
      (vertical 1.0
-              (post 1.0 point))))
+              (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
@@ -887,10 +960,14 @@ 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)
+    (message . gnus-message-buffer)
+    (mail . gnus-message-buffer)
+    (post-news . gnus-message-buffer)
     (faq . gnus-faq-buffer)
-    (picon . gnus-picon-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.")
 
@@ -904,10 +981,11 @@ inserts new groups at the beginning of the list of groups;
 `gnus-subscribe-alphabetically' inserts new groups in strict
 alphabetic order; `gnus-subscribe-hierarchically' inserts new groups
 in hierarchical newsgroup order; `gnus-subscribe-interactively' asks
-for your decision; `gnus-subscribe-killed' kills all new groups.")
+for your decision; `gnus-subscribe-killed' kills all new groups;
+`gnus-subscribe-zombies' will make all new groups into zombies.")
 
 ;; 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.
@@ -936,14 +1014,14 @@ 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',
 `gnus-group-sort-by-level', `gnus-group-sort-by-score', and
-`gnus-group-sort-by-rank'.  
+`gnus-group-sort-by-rank'.
 
-This variable can also be a list of sorting functions.  In that case,
+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 ?!
@@ -972,10 +1050,12 @@ list.")
   "*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 ?# 
+(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 ?+
@@ -1003,7 +1083,7 @@ list of parameters to that command.")
 (defvar gnus-insert-pseudo-articles t
   "*If non-nil, insert pseudo-articles when decoding articles.")
 
-(defvar gnus-group-line-format "%M%S%p%P%5y: %(%g%)\n"
+(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.
@@ -1026,6 +1106,7 @@ with some simple extensions.
 %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
@@ -1040,7 +1121,7 @@ the mouse point move inside the area.  There can only be one such area.
 
 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.
 
@@ -1048,7 +1129,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.
@@ -1083,6 +1164,7 @@ 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).
+%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
@@ -1091,22 +1173,22 @@ with some simple extensions.
      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,
+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 
+(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,
@@ -1138,41 +1220,43 @@ with some simple extensions:
   "*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}"
+(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:
 
 %S   The native news server.
-%M   The native select method.")
+%M   The native select method.
+%:   \":\" if %S isn't \"\".")
 
 (defvar gnus-valid-select-methods
   '(("nntp" post address prompt-address)
-    ("nnspool" post)
-    ("nnvirtual" post-mail virtual prompt-address) 
-    ("nnmbox" mail respool
-    ("nnml" mail respool)
-    ("nnmh" 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 prompt-address)
-    ("nndoc" none prompt-address) 
-    ("nnbabyl" mail respool) 
-    ("nnkiboze" post virtual) 
-    ("nnsoup" post-mail)
-    ("nnfolder" mail respool))
+    ("nneething" none address prompt-address)
+    ("nndoc" none address prompt-address)
+    ("nnbabyl" mail address respool)
+    ("nnkiboze" post 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
 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 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>.
@@ -1186,13 +1270,14 @@ of the modeline intact.")
 ;  "*Face used for mouse highlighting in Gnus.
 ;No mouse highlights will be done if `gnus-visual' is nil.")
 
-(defvar gnus-summary-mark-below nil
+(defvar gnus-summary-mark-below 0
   "*Mark all articles with a score below this variable as read.
 This variable is local to each summary buffer and usually set by the
-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.")
+  "*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.
@@ -1200,7 +1285,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',
@@ -1220,10 +1307,10 @@ Some functions you can use are `+', `max', or `min'.")
 
 (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 
+See `gnus-thread-score-function' for en explanation of what a
 \"thread score\" is.")
 
-(defvar gnus-auto-subscribed-groups 
+(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
@@ -1231,12 +1318,12 @@ 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
@@ -1248,15 +1335,19 @@ which to perform auto-expiry.  This only makes sense for mail groups.")
   "*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
+(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.
 
@@ -1270,14 +1361,20 @@ 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-group-update-group-hook nil
+  "*A hook called when updating group lines.")
+
 (defvar gnus-open-server-hook nil
   "*A hook called just before opening connection to the news server.")
 
@@ -1291,6 +1388,9 @@ 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;
@@ -1323,19 +1423,13 @@ If you want to run a special decoding program like nkf, use this hook.")
 ;The hook is designed to change the contents of the article
 ;buffer.  Typical functions that this hook may contain are
 ;`gnus-article-hide-headers' (hide selected headers),
-;`gnus-article-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)
 ;(add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
 ;(add-hook 'gnus-article-display-hook 'gnus-article-maybe-highlight)
 
-(defvar gnus-article-x-face-command
-  "{ 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.") 
-
 (defvar gnus-article-x-face-too-ugly nil
   "Regexp matching posters whose face shouldn't be shown automatically.")
 
@@ -1356,11 +1450,8 @@ following hook:
                       (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.
@@ -1380,14 +1471,15 @@ 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.")
 
-(defun gnus-parse-headers-hook nil
+(defvar gnus-parse-headers-hook nil
   "*A hook called before parsing the headers.")
+(add-hook 'gnus-parse-headers-hook 'gnus-decode-rfc1522)
 
 (defvar gnus-exit-group-hook nil
   "*A hook called when exiting (not quitting) summary mode.")
@@ -1398,6 +1490,9 @@ is not run if `gnus-visual' is nil.")
 (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 before saving any of the newsrc files.")
 
@@ -1409,7 +1504,7 @@ Can be used to turn version control on or off.")
   "*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 
+(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.
@@ -1418,38 +1513,84 @@ 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
 
-(defconst gnus-article-mark-lists 
-  '((marked . tick) (replied . reply) 
+(defvar gnus-tree-buffer "*Tree*"
+  "Buffer where Gnus thread trees are displayed.")
+
+;; Dummy variable.
+(defvar gnus-use-generic-from nil)
+
+(defvar gnus-thread-indent-array nil)
+(defvar gnus-thread-indent-array-level gnus-thread-indent-level)
+
+(defvar gnus-newsrc-file-version nil)
+
+(defvar gnus-method-history nil)
+;; Variable holding the user answers to all method prompts.
+
+(defvar gnus-group-history nil)
+;; Variable holding the user answers to all group prompts.
+
+(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)))
+    (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-topic-indentation "")
+(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)
@@ -1458,8 +1599,6 @@ automatically when it is selected.")
 (defvar gnus-override-method nil)
 (defvar gnus-article-check-size nil)
 
-(defvar gnus-nocem-hashtb nil)
-
 (defvar gnus-current-score-file nil)
 (defvar gnus-newsgroup-adaptive-score-file nil)
 (defvar gnus-scores-exclude-files nil)
@@ -1467,6 +1606,8 @@ automatically when it is selected.")
 (defvar gnus-opened-servers nil)
 
 (defvar gnus-current-move-group nil)
+(defvar gnus-current-copy-group nil)
+(defvar gnus-current-crosspost-group nil)
 
 (defvar gnus-newsgroup-dependencies nil)
 (defvar gnus-newsgroup-async nil)
@@ -1475,12 +1616,22 @@ automatically when it is selected.")
 (defvar gnus-newsgroup-adaptive nil)
 
 (defvar gnus-summary-display-table nil)
+(defvar gnus-summary-display-article-function nil)
+
+(defvar gnus-summary-highlight-line-function nil
+  "Function called after highlighting a summary line.")
 
-(defconst gnus-group-line-format-alist
+(defvar gnus-group-line-format-alist
   `((?M gnus-tmp-marked-mark ?c)
     (?S gnus-tmp-subscribed ?c)
     (?L gnus-tmp-level ?d)
-    (?N gnus-tmp-number ?s)
+    (?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)
@@ -1490,25 +1641,26 @@ automatically when it is selected.")
           (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d)
     (?g gnus-tmp-group ?s)
     (?G gnus-tmp-qualified-group ?s)
-    (?c (gnus-group-short-name gnus-tmp-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-topic-indentation ?s)
+    (?P gnus-group-indentation ?s)
+    (?l gnus-tmp-grouplens ?s)
     (?z gnus-tmp-news-method-string ?s)
     (?u gnus-tmp-user-defined ?s)))
 
-(defconst gnus-summary-line-format-alist 
+(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)) 
+    (?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)
@@ -1527,11 +1679,13 @@ automatically when it is selected.")
     (?\< (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 
+    (?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 
+    (?e (gnus-summary-number-of-articles-in-thread
         (and (boundp 'thread) (car thread)) gnus-tmp-level t)
        ?c)
     (?u gnus-tmp-user-defined ?s))
@@ -1539,35 +1693,36 @@ automatically when it is selected.")
 and what variables they correspond with, along with the type of the
 variable (string, integer, character, etc).")
 
-(defconst gnus-summary-dummy-line-format-alist
-  (` ((?S gnus-tmp-subject ?s)
-      (?N gnus-tmp-number ?d)
-      (?u gnus-tmp-user-defined ?s))))
-
-(defconst 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))))
-
-(defconst gnus-article-mode-line-format-alist  
+(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-and-unticked ?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)
 
-(defconst 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-group-mode-line-format-alist
+  `((?S gnus-tmp-news-server ?s)
+    (?M gnus-tmp-news-method ?s)
+    (?u gnus-tmp-user-defined ?s)
+    (?: gnus-tmp-colon ?s)))
 
 (defvar gnus-have-read-active-file nil)
 
@@ -1575,14 +1730,21 @@ variable (string, integer, character, etc).")
   "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
   "The mail address of the Gnus maintainers.")
 
-(defconst gnus-version "September Gnus v0.24"
+(defconst gnus-version-number "5.2.24"
   "Version number for this version of Gnus.")
 
+(defconst gnus-version (format "Gnus v%s" gnus-version-number)
+  "Version string for this version of Gnus.")
+
 (defvar gnus-info-nodes
-  '((gnus-group-mode           "(gnus)The Group Buffer")
-    (gnus-summary-mode         "(gnus)The Summary Buffer")
-    (gnus-article-mode         "(gnus)The Article Buffer"))
-  "Assoc list of major modes and related Info nodes.")
+  '((gnus-group-mode "(gnus)The Group Buffer")
+    (gnus-summary-mode "(gnus)The Summary Buffer")
+    (gnus-article-mode "(gnus)The Article Buffer")
+    (gnus-server-mode "(gnus)The Server Buffer")
+    (gnus-browse-mode "(gnus)Browse Foreign Server")
+    (gnus-tree-mode "(gnus)Tree Display")
+    )
+  "Alist of major modes and related Info nodes.")
 
 (defvar gnus-group-buffer "*Group*")
 (defvar gnus-summary-buffer "*Summary*")
@@ -1597,15 +1759,12 @@ variable (string, integer, character, etc).")
 (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-topic-topology gnus-topic-alist
@@ -1616,7 +1775,7 @@ variable (string, integer, character, etc).")
   "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.")
@@ -1742,6 +1901,8 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 (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)
@@ -1761,35 +1922,37 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 ;;; Let the byte-compiler know that we know about this variable.
 (defvar rmail-default-rmail-file)
 
-(defvar gnus-cache-removeable-articles nil)
+(defvar gnus-cache-removable-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-saved
     gnus-newsgroup-replied gnus-newsgroup-expirable
     gnus-newsgroup-processable gnus-newsgroup-killed
     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
     gnus-newsgroup-headers gnus-newsgroup-threads
-    gnus-newsgroup-prepared
+    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-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-async gnus-thread-expunge-below
+    gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
+    (gnus-summary-mark-below . global)
+    gnus-newsgroup-active gnus-scores-exclude-files
     gnus-newsgroup-history gnus-newsgroup-ancient
+    gnus-newsgroup-sparse
     (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
     gnus-newsgroup-adaptive-score-file
     (gnus-newsgroup-expunged-tally . 0)
-    gnus-cache-removeable-articles gnus-newsgroup-cached
+    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.")
@@ -1799,14 +1962,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.
@@ -1821,10 +1984,10 @@ Thank you for your help in stamping out bugs.
 
   ;; This little mapcar goes through the list below and marks the
   ;; symbols in question as autoloaded functions.
-  (mapcar 
+  (mapcar
    (lambda (package)
      (let ((interactive (nth 1 (memq ':interactive package))))
-       (mapcar 
+       (mapcar
        (lambda (function)
          (let (keymap)
            (when (consp function)
@@ -1843,96 +2006,103 @@ Thank you for your help in stamping out bugs.
      ("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-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-mh" gnus-mh-mail-setup gnus-summary-save-article-folder 
+     ("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-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-hide gnus-article-hide-signature 
-      gnus-article-highlight-headers gnus-article-highlight-signature 
-      gnus-article-add-buttons gnus-article-add-buttons-to-head 
+      gnus-article-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-nocem" gnus-nocem-scan-groups gnus-nocem-close)
+     ("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-kill" gnus-kill gnus-apply-kill-file-internal 
-      gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author 
+      gnus-article-highlight-citation gnus-article-hide-citation-maybe
+      gnus-article-hide-citation gnus-article-fill-cited-article
+      gnus-article-hide-citation-in-followups)
+     ("gnus-kill" gnus-kill gnus-apply-kill-file-internal
+      gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author
       gnus-execute gnus-expunge)
      ("gnus-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-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-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-summary-raise-score 
+      gnus-summary-set-score gnus-summary-current-score)
+     ("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-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-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-article-mail 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-post-news gnus-inews-news 
       gnus-summary-reply gnus-summary-reply-with-original
       gnus-summary-mail-forward gnus-summary-mail-other-window
       gnus-bug)
-     ("gnus-picon" gnus-article-display-picons)
+     ("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)
+     ("smiley" :interactive t gnus-smiley-display)
      ("gnus-vm" gnus-vm-mail-setup)
      ("gnus-vm" :interactive t gnus-summary-save-in-vm
-      gnus-summary-save-article-vm gnus-yank-article))))
+      gnus-summary-save-article-vm))))
 
 \f
 
@@ -1944,14 +2114,28 @@ Thank you for your help in stamping out bugs.
 
 ;;; 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 return to the original window."
-  `(let ((GnusStartBufferWindow (selected-window)))
-     (unwind-protect
-        (progn
-          (pop-to-buffer ,buffer)
-          ,@forms)
-       (select-window GnusStartBufferWindow))))
+  (let ((tempvar (make-symbol "GnusStartBufferWindow"))
+       (w (make-symbol "w"))
+       (buf (make-symbol "buf")))
+    `(let* ((,tempvar (selected-window))
+           (,buf ,buffer)
+           (,w (get-buffer-window ,buf 'visible)))
+       (unwind-protect
+          (progn
+            (if ,w
+                (select-window ,w)
+              (pop-to-buffer ,buf))
+            ,@forms)
+        (select-window ,tempvar)))))
+
+(put 'gnus-eval-in-buffer-window 'lisp-indent-function 1)
+(put 'gnus-eval-in-buffer-window 'lisp-indent-hook 1)
+(put 'gnus-eval-in-buffer-window 'edebug-form-spec '(form body))
 
 (defmacro gnus-gethash (string hashtable)
   "Get hash value of STRING in HASHTABLE."
@@ -1972,6 +2156,10 @@ Thank you for your help in stamping out bugs.
   "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))
@@ -2000,13 +2188,19 @@ Thank you for your help in stamping out bugs.
       (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)
   `(let ((buf ,buffer))
@@ -2029,6 +2223,23 @@ Thank you for your help in stamping out bugs.
        (point)
       (goto-char p))))
 
+(defun gnus-alive-p ()
+  "Say whether Gnus is running or not."
+  (and gnus-group-buffer
+       (get-buffer gnus-group-buffer)))
+
+(defun gnus-delete-first (elt list)
+  "Delete by side effect the first occurrence of ELT as a member of LIST."
+  (if (equal (car list) elt)
+      (cdr list)
+    (let ((total list))
+      (while (and (cdr list)
+                 (not (equal (cadr list) elt)))
+       (setq list (cdr list)))
+      (when (cdr list)
+       (setcdr list (cddr list)))
+      total)))
+
 ;; Delete the current line (and the next N lines.);
 (defmacro gnus-delete-line (&optional n)
   `(delete-region (progn (beginning-of-line) (point))
@@ -2041,12 +2252,15 @@ Thank you for your help in stamping out bugs.
       (setq gnus-init-inhibit nil)
     (setq gnus-init-inhibit inhibit-next)
     (and gnus-init-file
-        (or (and (file-exists-p 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))))
+        (condition-case var
+            (load gnus-init-file nil t)
+          (error
+           (error "Error in %s: %s" gnus-init-file var))))))
 
 ;; Info access macros.
 
@@ -2106,23 +2320,49 @@ Thank you for your help in stamping out bugs.
        (let ((flist (append fval nil)))
          (setcar flist 'byte-code)
          flist)
-      (cons 'progn (cdr (cdr fval))))))
+      (cons 'progn (cddr fval)))))
 
-;;; Load the user startup file.
-;; (eval '(gnus-read-init-file 'inhibit))
+;; Find out whether the gnus-visual TYPE is wanted.
+(defun gnus-visual-p (&optional type class)
+  (and gnus-visual                     ; Has to be non-nil, at least.
+       (if (not type)                  ; We don't care about type.
+          gnus-visual
+        (if (listp gnus-visual)        ; It's a list, so we check it.
+            (or (memq type gnus-visual)
+                (memq class gnus-visual))
+          t))))
 
-;;; Load the compatability functions. 
+;;; Load the 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. 
+;; flexibility of the user-defined format specs.
 
 ;; First we have lots of dummy defvars to let the compiler know these
 ;; are really dynamic variables.
@@ -2153,54 +2393,54 @@ Thank you for your help in stamping out bugs.
 (defvar gnus-mouse-face-prop)
 
 (defun gnus-summary-line-format-spec ()
-  (insert gnus-tmp-unread gnus-tmp-replied 
+  (insert gnus-tmp-unread gnus-tmp-replied
          gnus-tmp-score-char gnus-tmp-indentation)
-  (put-text-property
+  (gnus-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) 
+     (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 
+(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
+  (gnus-put-text-property
    (point)
    (progn
-     (insert ":                          :")
+     (insert ":                                 :")
      (point))
    gnus-mouse-face-prop gnus-mouse-face)
   (insert " " gnus-tmp-subject "\n"))
 
-(defvar gnus-summary-dummy-line-format-spec 
+(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 
+  (insert gnus-tmp-marked-mark gnus-tmp-subscribed
          gnus-tmp-process-marked
-         gnus-topic-indentation
+         gnus-group-indentation
          (format "%5s: " gnus-tmp-number-of-unread))
-  (put-text-property 
+  (gnus-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 
+(defvar gnus-group-line-format-spec
   (gnus-byte-code 'gnus-group-line-format-spec))
 
-(defvar gnus-format-specs 
+(defvar gnus-format-specs
   `((version . ,emacs-version)
     (group ,gnus-group-line-format ,gnus-group-line-format-spec)
     (summary-dummy ,gnus-summary-dummy-line-format
@@ -2211,7 +2451,7 @@ Thank you for your help in stamping out bugs.
 (defvar gnus-summary-mode-line-format-spec nil)
 (defvar gnus-group-mode-line-format-spec nil)
 
-;;; Phew.  All that gruft is over, fortunately.  
+;;; Phew.  All that gruft is over, fortunately.
 
 \f
 ;;;
@@ -2227,24 +2467,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
-        ;; 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)))
+        ;; 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))))
@@ -2253,24 +2493,15 @@ 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)
-       (mail-fetch-field field)))))
+      (let ((case-fold-search t)
+           (inhibit-point-motion-hooks t))
+       (nnheader-narrow-to-headers)
+       (message-fetch-field field)))))
 
 (defun gnus-goto-colon ()
   (beginning-of-line)
   (search-forward ":" (gnus-point-at-eol) t))
 
-(defun gnus-narrow-to-headers ()
-  "Narrow to the head of an article."
-  (widen)
-  (narrow-to-region
-   (goto-char (point-min))
-   (if (search-forward "\n\n" nil t)
-       (1- (point))
-     (point-max)))
-  (goto-char (point-min)))
-
 ;;;###autoload
 (defun gnus-update-format (var)
   "Update the format specification near point."
@@ -2283,91 +2514,122 @@ Thank you for your help in stamping out bugs.
       ;; Search backward.
       (when (re-search-backward "\\(gnus-[-a-z]+-line-format\\)" nil t)
        (match-string 1)))))
-  (set
-   (intern (format "%s-spec" var))
-   (gnus-parse-format (symbol-value (intern var))
-                     (symbol-value (intern (format "%s-alist" var)))
-                     (not (string-match "mode" var))))
-  (pop-to-buffer "*Gnus Format*")
-  (erase-buffer)
-  (lisp-interaction-mode)
-  (insert (pp-to-string (symbol-value (intern (format "%s-spec" var))))))
-
+  (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 (&optional force)
   "Update all (necessary) format specifications."
   ;; Make the indentation array.
   (gnus-make-thread-indent-array)
 
+  ;; See whether all the stored info needs to be flushed.
   (when (or force
-           (and (assq 'version gnus-format-specs)
-                (not (equal emacs-version
-                            (cdr (assq 'version gnus-format-specs))))))
+           (not (equal emacs-version
+                       (cdr (assq 'version gnus-format-specs)))))
     (setq gnus-format-specs nil))
 
-  (let ((types '(summary summary-dummy group 
-                          summary-mode group-mode article-mode))
-       old-format new-format entry type val)
-    (while types
-      (setq type (pop types))
-      (setq new-format (symbol-value
-                       (intern (format "gnus-%s-line-format" type))))
+  ;; 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))
-         (set (intern (format "gnus-%s-line-format-spec" type)) 
-              (car (cdr entry)))
+         ;; 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)) 
+             (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 
+                (symbol-value
                  (intern (format "gnus-%s-line-format-alist"
                                  (if (eq type 'article-mode)
                                      'summary-mode type))))
                 (not (string-match "mode$" (symbol-name type))))))
-       (set (intern (format "gnus-%s-line-format-spec" type)) val)
-       (if entry 
-           (setcar (cdr entry) val)
-         (push (list type new-format val) gnus-format-specs)))))
-      
-  (gnus-update-group-mark-positions)
-  (gnus-update-summary-mark-positions)
+       ;; 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 "%[-,0-9]*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
+    (when (and gnus-summary-buffer
+              (get-buffer gnus-summary-buffer)
+              (buffer-name (get-buffer gnus-summary-buffer)))
+      (set-buffer gnus-summary-buffer))
     (let ((gnus-replied-mark 129)
          (gnus-score-below-mark 130)
          (gnus-score-over-mark 130)
          (thread nil)
          (gnus-visual nil)
+         (spec gnus-summary-line-format-spec)
          pos)
-      (gnus-set-work-buffer)
-      (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))
-      (goto-char (point-min))
-      (setq pos (cons (cons 'score (and (search-forward "\202" nil t)
-                                       (- (point) 2))) pos))
+      (save-excursion
+       (gnus-set-work-buffer)
+       (let ((gnus-summary-line-format-spec spec))
+         (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))
+         (push (cons 'replied (and (search-forward "\201" nil t) 
+                                   (- (point) 2)))
+               pos)
+         (goto-char (point-min))
+         (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-group-marked '("dummy.group"))
+         (gnus-active-hashtb (make-vector 10 0)))
       (gnus-set-active "dummy.group" '(0 . 0))
       (gnus-set-work-buffer)
       (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
@@ -2383,9 +2645,9 @@ Thank you for your help in stamping out bugs.
 (defvar gnus-mouse-face-4 'highlight)
 
 (defun gnus-mouse-face-function (form type)
-  `(put-text-property
+  `(gnus-put-text-property
     (point) (progn ,@form (point))
-    gnus-mouse-face-prop 
+    gnus-mouse-face-prop
     ,(if (equal type 0)
         'gnus-mouse-face
        `(quote ,(symbol-value (intern (format "gnus-mouse-face-%d" type)))))))
@@ -2397,7 +2659,7 @@ Thank you for your help in stamping out bugs.
 (defvar gnus-face-4 'bold)
 
 (defun gnus-face-face-function (form type)
-  `(put-text-property
+  `(gnus-put-text-property
     (point) (progn ,@form (point))
     'face ',(symbol-value (intern (format "gnus-face-%d" type)))))
 
@@ -2411,15 +2673,15 @@ Thank you for your help in stamping out bugs.
        (if (numberp val)
           (setq val (int-to-string val)))
        (if (> (length val) ,max-width)
-          (substring val 0 ,max-width))
-       val)))
+          (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 
+  (if (string-match
        "\\`\\(.*\\)%[0-9]?[{(]\\(.*\\)%[0-9]?[})]\\(.*\n?\\)\\'"
        format)
       (gnus-parse-complex-format format spec-alist)
@@ -2455,17 +2717,15 @@ Thank you for your help in stamping out bugs.
         (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 
-                      (cdr (cdr sform)) spec-alist)
+            (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 a
-  ;; string.  
+  ;; string.
   (let ((max-width 0)
        spec flist fstring newspec elem beg result dontinsert)
     (save-excursion
@@ -2481,9 +2741,9 @@ Thank you for your help in stamping out bugs.
          ;; "%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 
+             (setq max-width
+                   (string-to-int
+                    (buffer-substring
                      (1+ (match-beginning 1)) (match-end 1))))
            (setq max-width 0)
            (setq beg (match-beginning 2)))
@@ -2493,23 +2753,23 @@ Thank you for your help in stamping out bugs.
          ;; Treat user defined format specifiers specially.
          (when (eq (car elem) 'gnus-tmp-user-defined)
            (setq elem
-                 (list 
+                 (list
                   (list (intern (concat "gnus-user-format-function-"
                                         (match-string 3)))
                         'gnus-tmp-header) ?s))
            (delete-region (match-beginning 3) (match-end 3)))
          (if (not (zerop max-width))
              (let ((el (car elem)))
-               (cond ((= (car (cdr elem)) ?c) 
+               (cond ((= (cadr elem) ?c)
                       (setq el (list 'char-to-string el)))
-                     ((= (car (cdr elem)) ?d)
-                      (numberp el) (setq el (list 'int-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 (car (cdr elem))))))
+           (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.
@@ -2517,9 +2777,9 @@ Thank you for your help in stamping out bugs.
        (insert newspec))
       (setq fstring (buffer-substring 1 (point-max))))
     ;; Do some postprocessing to increase efficiency.
-    (setq 
+    (setq
      result
-     (cond 
+     (cond
       ;; Emptyness.
       ((string= fstring "")
        nil)
@@ -2559,14 +2819,18 @@ Thank you for your help in stamping out bugs.
          (if dontinsert
              result
            (cons 'insert result)))
-      (or (car 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 INSERT, insert the result."
+If PROPS, insert the result."
   (let ((form (gnus-parse-format format alist props)))
     (if props
-       (add-text-properties (point) (progn (eval form) (point)) props)
+       (gnus-add-text-properties (point) (progn (eval form) (point)) props)
       (eval form))))
 
 (defun gnus-remove-text-with-property (prop)
@@ -2600,7 +2864,7 @@ Otherwise, it is like ~/News/news/group/num."
                       (gnus-capitalize-newsgroup newsgroup)
                     (gnus-newsgroup-directory-form newsgroup))
                   "/" (int-to-string (mail-header-number headers)))
-          (or gnus-article-save-directory "~/News"))))
+          gnus-article-save-directory)))
     (if (and last-file
             (string-equal (file-name-directory default)
                           (file-name-directory last-file))
@@ -2611,14 +2875,14 @@ 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 (mail-header-number headers)))
-          (or gnus-article-save-directory "~/News"))))
+          gnus-article-save-directory)))
     (if (and last-file
             (string-equal (file-name-directory default)
                           (file-name-directory last-file))
@@ -2635,7 +2899,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        (if (gnus-use-long-file-name 'not-save)
           (gnus-capitalize-newsgroup newsgroup)
         (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
-       (or gnus-article-save-directory "~/News"))))
+       gnus-article-save-directory)))
 
 (defun gnus-plain-save-name (newsgroup headers &optional last-file)
   "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
@@ -2646,7 +2910,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        (if (gnus-use-long-file-name 'not-save)
           newsgroup
         (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
-       (or gnus-article-save-directory "~/News"))))
+       gnus-article-save-directory)))
 
 ;; For subscribing new newsgroup
 
@@ -2662,26 +2926,29 @@ 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))
+             (while (not (memq (setq ans (read-char)) '(?y ?\n ?n ?s ?q)))
+               (ding)
+               (message "Descend hierarchy %s? ([y]nsq): "
+                        (substring prefix 1 (1- (length prefix)))))
              (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))
@@ -2695,7 +2962,9 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                       (setq groups (cdr groups))))
                    (t nil)))
          (message "Subscribe %s? ([n]yq)" (car groups))
-         (setq ans (read-char))
+         (while (not (memq (setq ans (read-char)) '(?y ?\n ?q ?n)))
+           (ding)
+           (message "Subscribe %s? ([n]yq)" (car groups)))
          (setq group (car groups))
          (cond ((= ans ?y)
                 (gnus-subscribe-alphabetically (car groups))
@@ -2706,7 +2975,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)))))))
@@ -2717,12 +2986,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)))
 
@@ -2765,10 +3033,10 @@ it is killed."
 
 (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))
@@ -2777,11 +3045,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))
@@ -2792,14 +3060,14 @@ 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))
         dirs err)
@@ -2816,7 +3084,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)
@@ -2825,19 +3093,24 @@ 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))
 
@@ -2845,35 +3118,41 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
 ;; all whitespace.
 ;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
 (defun gnus-simplify-buffer-fuzzy ()
-  (goto-char (point-min))
-  (while (or
-         (looking-at "^[ \t]*\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;][ \t]*")
-         (looking-at "^[[].*:[ \t].*[]]$"))
+  (let ((case-fold-search t))
+    (goto-char (point-min))
+    (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]*\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;][ \t]*"
-                             nil t)
+    (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
       (replace-match "" t t))
     (goto-char (point-min))
-    (while (re-search-forward "^[[].*:[ \t].*[]]$" 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]*$" nil t)
-    (replace-match "" t t))
-  (goto-char (point-min))
-  (while (re-search-forward "[ \t]+" nil t)
-    (replace-match " " t t))
-  (goto-char (point-min))
-  (while (re-search-forward "[ \t]+$" nil t)
-    (replace-match "" t t))
-  (goto-char (point-min))
-  (while (re-search-forward "^[ \t]+" nil t)
-    (replace-match "" t t))
-  (goto-char (point-min))
-  (if gnus-simplify-subject-fuzzy-regexp
+    (while (re-search-forward "  +" nil t)
+      (replace-match " " t t))
+    (goto-char (point-min))
+    (while (re-search-forward " $" nil t)
+      (replace-match "" t t))
+    (goto-char (point-min))
+    (while (re-search-forward "^ +" nil t)
+      (replace-match "" t t))
+    (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
@@ -2882,18 +3161,18 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
                (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."
-  (let ((case-fold-search t))
-    (save-excursion
-      (gnus-set-work-buffer)
+  (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 the list of buffers to be killed on exit.
 (defun gnus-add-current-to-buffer-list ()
   (or (memq (current-buffer) gnus-buffer-list)
       (setq gnus-buffer-list (cons (current-buffer) gnus-buffer-list))))
@@ -2902,38 +3181,9 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
   (not (or (string< s1 s2)
           (string= s1 s2))))
 
-;; Functions accessing headers.
-;; Functions are more convenient than macros in some cases.
-
-(defun gnus-header-number (header)
-  (mail-header-number header))
-
-(defun gnus-header-subject (header)
-  (mail-header-subject header))
-
-(defun gnus-header-from (header)
-  (mail-header-from header))
-
-(defun gnus-header-xref (header)
-  (mail-header-xref header))
-
-(defun gnus-header-lines (header)
-  (mail-header-lines header))
-
-(defun gnus-header-date (header)
-  (mail-header-date header))
-
-(defun gnus-header-id (header)
-  (mail-header-id header))
-
-(defun gnus-header-message-id (header)
-  (mail-header-id header))
-
-(defun gnus-header-chars (header)
-  (mail-header-chars header))
-
-(defun gnus-header-references (header)
-  (mail-header-references header))
+(defun gnus-read-active-file-p ()
+  "Say whether the active file has been read from `gnus-select-method'."
+  (memq gnus-select-method gnus-have-read-active-file))
 
 ;;; General various misc type functions.
 
@@ -2955,56 +3205,60 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
        gnus-active-hashtb nil
        gnus-moderated-list nil
        gnus-description-hashtb nil
+       gnus-current-headers nil
+       gnus-thread-indent-array nil
        gnus-newsgroup-headers nil
        gnus-newsgroup-name nil
        gnus-server-alist nil
+       gnus-group-list-mode nil
        gnus-opened-servers nil
        gnus-current-select-method nil)
-  ;; Reset any score variables.
-  (and gnus-use-scoring (gnus-score-close))
+  (gnus-shutdown 'gnus)
   ;; Kill the startup file.
   (and gnus-current-startup-file
        (get-file-buffer gnus-current-startup-file)
        (kill-buffer (get-file-buffer gnus-current-startup-file)))
-  ;; Save any cache buffers.
-  (and gnus-use-cache (gnus-cache-save-buffers))
   ;; Clear the dribble buffer.
   (gnus-dribble-clear)
-  ;; Close down NoCeM.
-  (and gnus-use-nocem (gnus-nocem-close))
-  ;; Shut down the demons.
-  (and gnus-use-demon (gnus-demon-cancel))
   ;; Kill global KILL file buffer.
-  (if (get-file-buffer (gnus-newsgroup-kill-file nil))
-      (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
+  (when (get-file-buffer (gnus-newsgroup-kill-file nil))
+    (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
   (gnus-kill-buffer nntp-server-buffer)
-  ;; Backlog.
-  (and gnus-keep-backlog (gnus-backlog-shutdown))
   ;; Kill Gnus buffers.
   (while gnus-buffer-list
-    (gnus-kill-buffer (car gnus-buffer-list))
-    (setq gnus-buffer-list (cdr gnus-buffer-list))))
+    (gnus-kill-buffer (pop gnus-buffer-list)))
+  ;; Remove Gnus frames.
+  (gnus-kill-gnus-frames))
+
+(defun gnus-kill-gnus-frames ()
+  "Kill all frames Gnus has created."
+  (while gnus-created-frames
+    (when (frame-live-p (car gnus-created-frames))
+      ;; We slap a condition-case around this `delete-frame' to ensure 
+      ;; against errors if we try do delete the single frame that's left.
+      (condition-case ()
+         (delete-frame (car gnus-created-frames))
+       (error nil)))
+    (pop gnus-created-frames)))
 
 (defun gnus-windows-old-to-new (setting)
   ;; First we take care of the really, really old Gnus 3 actions.
-  (if (symbolp setting)
-      (setq setting 
-           (cond ((memq setting '(SelectArticle))
-                  'article)
-                 ((memq setting '(SelectSubject ExpandSubject))
-                  'summary)
-                 ((memq setting '(SelectNewsgroup ExitNewsgroup))
-                  'group)
-                 (t setting))))
+  (when (symbolp setting)
+    (setq setting
+         ;; Take care of ooold GNUS 3.x values.
+         (cond ((eq setting 'SelectArticle) 'article)
+               ((memq setting '(SelectSubject ExpandSubject)) 'summary)
+               ((memq setting '(SelectNewsgroup ExitNewsgroup)) 'group)
+               (t setting))))
   (if (or (listp setting)
          (not (and gnus-window-configuration
                    (memq setting '(group summary article)))))
       setting
-    (let* ((setting (if (eq setting 'group) 
+    (let* ((setting (if (eq setting 'group)
                        (if (assq 'newsgroup gnus-window-configuration)
                            'newsgroup
                          'newsgroups) setting))
-          (elem (car (cdr (assq setting gnus-window-configuration))))
+          (elem (cadr (assq setting gnus-window-configuration)))
           (total (apply '+ elem))
           (types '(group summary article))
           (pbuf (if (eq setting 'newsgroups) 'group 'summary))
@@ -3015,19 +3269,25 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
        (or (not (numberp (nth i elem)))
            (zerop (nth i elem))
            (progn
-             (setq perc  (/ (* 1.0 (nth 0 elem)) total))
+             (setq perc (if (= i 2)
+                            1.0
+                          (/ (float (nth 0 elem)) total)))
              (setq out (cons (if (eq pbuf (nth i types))
-                                 (vector (nth i types) perc 'point)
-                               (vector (nth i types) perc))
+                                 (list (nth i types) perc 'point)
+                               (list (nth i types) perc))
                              out))))
        (setq i (1+ i)))
-      (list (nreverse out)))))
-          
+      `(vertical 1.0 ,@(nreverse out)))))
+
+;;;###autoload
 (defun gnus-add-configuration (conf)
-  (setq gnus-buffer-configuration 
+  "Add the window configuration CONF to `gnus-buffer-configuration'."
+  (setq gnus-buffer-configuration
        (cons conf (delq (assq (car conf) gnus-buffer-configuration)
                         gnus-buffer-configuration))))
 
+(defvar gnus-frame-list nil)
+
 (defun gnus-configure-frame (split &optional window)
   "Split WINDOW according to SPLIT."
   (unless window
@@ -3040,21 +3300,26 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
            (vectorp (car split)))
     (push 1.0 split)
     (push 'vertical split))
-  ;; The SPLIT might be something that is to be evaled to 
+  ;; The SPLIT might be something that is to be evaled to
   ;; return a new SPLIT.
   (while (and (not (assq (car split) gnus-window-to-buffer))
              (gnus-functionp (car split)))
     (setq split (eval split)))
   (let* ((type (car split))
-        (subs (cdr (cdr split)))
-        (len (if (eq type 'horizontal) (window-width) (window-height) ))
+        (subs (cddr split))
+        (len (if (eq type 'horizontal) (window-width) (window-height)))
         (total 0)
+        (window-min-width (or gnus-window-min-width window-min-width))
+        (window-min-height (or gnus-window-min-height window-min-height))
         s result new-win rest comp-subs size sub)
     (cond
      ;; Nothing to do here.
      ((null split))
+     ;; Don't switch buffers.
+     ((null type)
+      (and (memq 'point split) window))
      ;; This is a buffer to be selected.
-     ((not (or (eq type 'horizontal) (eq type 'vertical)))
+     ((not (memq type '(frame horizontal vertical)))
       (let ((buffer (cond ((stringp type) type)
                          (t (cdr (assq type gnus-window-to-buffer)))))
            buf)
@@ -3067,6 +3332,34 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
        (switch-to-buffer buf)
        ;; We return the window if it has the `point' spec.
        (and (memq 'point split) window)))
+     ;; This is a frame split.
+     ((eq type 'frame)
+      (unless gnus-frame-list
+       (setq gnus-frame-list (list (window-frame
+                                    (get-buffer-window (current-buffer))))))
+      (let ((i 0)
+           params frame fresult)
+       (while (< i (length subs))
+         ;; Frame parameter is gotten from the sub-split.
+         (setq params (cadr (elt subs i)))
+         ;; It should be a list.
+         (unless (listp params)
+           (setq params nil))
+         ;; Create a new frame?
+         (unless (setq frame (elt gnus-frame-list i))
+           (nconc gnus-frame-list (list (setq frame (make-frame params))))
+           (push frame gnus-created-frames))
+         ;; Is the old frame still alive?
+         (unless (frame-live-p frame)
+           (setcar (nthcdr i gnus-frame-list)
+                   (setq frame (make-frame params))))
+         ;; Select the frame in question and do more splits there.
+         (select-frame frame)
+         (setq fresult (or (gnus-configure-frame (elt subs i)) fresult))
+         (incf i))
+       ;; Select the frame that has the selected buffer.
+       (when fresult
+         (select-frame (window-frame fresult)))))
      ;; This is a normal split.
      (t
       (when (> (length subs) 0)
@@ -3090,12 +3383,10 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
                   (error "Illegal size: %s" size)))
            ;; Try to make sure that we are inside the safe limits.
            (cond ((zerop s))
-                 ((and (eq type 'horizontal)
-                       (< s 10))
-                  (setq s 10))
-                 ((and (eq type 'vertical)
-                       (< s 4))
-                  (setq s 4)))
+                 ((eq type 'horizontal)
+                  (setq s (max s window-min-width)))
+                 ((eq type 'vertical)
+                  (setq s (max s window-min-height))))
            (setcar (cdar comp-subs) s)
            (incf total s)))
        ;; Take care of the "1.0" spec.
@@ -3111,7 +3402,7 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
            (setq new-win
                  (split-window window (cadar comp-subs)
                                (eq type 'horizontal))))
-         (setq result (or (gnus-configure-frame 
+         (setq result (or (gnus-configure-frame
                            (car comp-subs) window) result))
          (select-window new-win)
          (setq window new-win)
@@ -3120,73 +3411,100 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
       (when result
        (select-window result))))))
 
+(defvar gnus-frame-split-p nil)
+
 (defun gnus-configure-windows (setting &optional force)
   (setq setting (gnus-windows-old-to-new setting))
   (let ((split (if (symbolp setting)
-                  (car (cdr (assq setting gnus-buffer-configuration)))
+                  (cadr (assq setting gnus-buffer-configuration))
                 setting))
-       (in-buf (current-buffer))
-       rule val w height hor ohor heights sub jump-buffer
-       rel total to-buf all-visible)
+       all-visible)
+
+    (setq gnus-frame-split-p nil)
 
     (unless split
       (error "No such setting: %s" setting))
 
-    (if (and (not force) (setq all-visible (gnus-all-windows-visible-p split)))
+    (if (and (setq all-visible (gnus-all-windows-visible-p split))
+            (not force))
        ;; All the windows mentioned are already visible, so we just
        ;; put point in the assigned buffer, and do not touch the
-       ;; winconf. 
+       ;; winconf.
        (select-window all-visible)
 
       ;; Either remove all windows or just remove all Gnus windows.
-      (if gnus-use-full-window
-         (delete-other-windows)
-       (gnus-remove-some-windows)
-       (switch-to-buffer nntp-server-buffer))
+      (let ((frame (selected-frame)))
+       (unwind-protect
+           (if gnus-use-full-window
+               ;; We want to remove all other windows.
+               (if (not gnus-frame-split-p)
+                   ;; This is not a `frame' split, so we ignore the
+                   ;; other frames.  
+                   (delete-other-windows)
+                 ;; This is a `frame' split, so we delete all windows
+                 ;; on all frames.
+                 (mapcar 
+                  (lambda (frame)
+                    (unless (eq (cdr (assq 'minibuffer
+                                           (frame-parameters frame)))
+                                'only)
+                      (select-frame frame)
+                      (delete-other-windows)))
+                  (frame-list)))
+             ;; Just remove some windows.
+             (gnus-remove-some-windows)
+             (switch-to-buffer nntp-server-buffer))
+         (select-frame frame)))
 
       (switch-to-buffer nntp-server-buffer)
       (gnus-configure-frame split (get-buffer-window (current-buffer))))))
 
 (defun gnus-all-windows-visible-p (split)
-  (when (vectorp split)
-    (setq split (append split nil)))
-  (when (or (consp (car split))
-           (vectorp (car split)))
-    (push 1.0 split)
-    (push 'vertical split))
-  ;; The SPLIT might be something that is to be evaled to 
-  ;; return a new SPLIT.
-  (while (and (not (assq (car split) gnus-window-to-buffer))
-             (gnus-functionp (car split)))
-    (setq split (eval split)))
-  (let* ((type (elt split 0)))
-    (cond
-     ((null split)
-      t)
-     ((not (or (eq type 'horizontal) (eq type 'vertical)))
-      (let ((buffer (cond ((stringp type) type)
-                         (t (cdr (assq type gnus-window-to-buffer)))))
-           win buf)
+  "Say whether all buffers in SPLIT are currently visible.
+In particular, the value returned will be the window that
+should have point."
+  (let ((stack (list split))
+       (all-visible t)
+       type buffer win buf)
+    (while (and (setq split (pop stack))
+               all-visible)
+      ;; Be backwards compatible.
+      (when (vectorp split)
+       (setq split (append split nil)))
+      (when (or (consp (car split))
+               (vectorp (car split)))
+       (push 1.0 split)
+       (push 'vertical split))
+      ;; The SPLIT might be something that is to be evaled to
+      ;; return a new SPLIT.
+      (while (and (not (assq (car split) gnus-window-to-buffer))
+                 (gnus-functionp (car split)))
+       (setq split (eval split)))
+
+      (setq type (elt split 0))
+      (cond
+       ;; Nothing here.
+       ((null split) t)
+       ;; A buffer.
+       ((not (memq type '(horizontal vertical frame)))
+       (setq buffer (cond ((stringp type) type)
+                          (t (cdr (assq type gnus-window-to-buffer)))))
        (unless buffer
          (error "Illegal buffer type: %s" type))
-       (when (setq buf (get-buffer (if (symbolp buffer) (symbol-value buffer) 
+       (when (setq buf (get-buffer (if (symbolp buffer)
+                                       (symbol-value buffer)
                                      buffer)))
-         (setq win (get-buffer-window buf)))
-       (when win
-         (if (memq 'point split)
-             win
-           t))))
-     (t
-      (let ((n (mapcar 'gnus-all-windows-visible-p
-                      (cdr (cdr split))))
-           (win t))
-       (while n
-         (cond ((windowp (car n))
-                (setq win (car n)))
-               ((null (car n))
-                (setq win nil)))
-         (setq n (cdr n)))
-       win)))))
+         (setq win (get-buffer-window buf t)))
+       (if win
+           (when (memq 'point split)
+               (setq all-visible win))
+         (setq all-visible nil)))
+       (t
+       (when (eq type 'frame)
+         (setq gnus-frame-split-p t))
+       (setq stack (append (cddr split) stack)))))
+    (unless (eq all-visible t)
+      all-visible)))
 
 (defun gnus-window-top-edge (&optional window)
   (nth 1 (window-edges window)))
@@ -3197,10 +3515,10 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
     (save-excursion
       ;; Remove windows on all known Gnus buffers.
       (while buffers
-       (setq buf (cdr (car buffers)))
+       (setq buf (cdar buffers))
        (if (symbolp buf)
            (setq buf (and (boundp buf) (symbol-value buf))))
-       (and buf 
+       (and buf
             (get-buffer-window buf)
             (progn
               (setq bufs (cons buf bufs))
@@ -3212,20 +3530,19 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
                     (setq lowest-buf buf)))))
        (setq buffers (cdr buffers)))
       ;; Remove windows on *all* summary buffers.
-      (let (wins)
-       (walk-windows
-        (lambda (win)
-          (let ((buf (window-buffer win)))
-            (if (string-match  "^\\*Summary" (buffer-name buf))
-                (progn
-                  (setq bufs (cons buf bufs))
-                  (pop-to-buffer buf)
-                  (if (or (not lowest)
-                          (< (gnus-window-top-edge) lowest))
-                      (progn
-                        (setq lowest-buf buf)
-                        (setq lowest (gnus-window-top-edge))))))))))
-      (and lowest-buf 
+      (walk-windows
+       (lambda (win)
+        (let ((buf (window-buffer win)))
+          (if (string-match    "^\\*Summary" (buffer-name buf))
+              (progn
+                (setq bufs (cons buf bufs))
+                (pop-to-buffer buf)
+                (if (or (not lowest)
+                        (< (gnus-window-top-edge) lowest))
+                    (progn
+                      (setq lowest-buf buf)
+                      (setq lowest (gnus-window-top-edge)))))))))
+      (and lowest-buf
           (progn
             (pop-to-buffer lowest-buf)
             (switch-to-buffer nntp-server-buffer)))
@@ -3233,48 +3550,37 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
        (and (not (eq (car bufs) lowest-buf))
             (delete-windows-on (car bufs)))
        (setq bufs (cdr bufs))))))
-                         
-(defun gnus-version ()
-  "Version numbers of this version of Gnus."
-  (interactive)
+
+(defun gnus-version (&optional arg)
+  "Version number of this version of Gnus.
+If ARG, insert string at point."
+  (interactive "P")
   (let ((methods gnus-valid-select-methods)
        (mess gnus-version)
        meth)
     ;; Go through all the legal select methods and add their version
     ;; numbers to the total version string.  Only the backends that are
     ;; currently in use will have their message numbers taken into
-    ;; consideration. 
+    ;; consideration.
     (while methods
-      (setq meth (intern (concat (car (car methods)) "-version")))
+      (setq meth (intern (concat (caar methods) "-version")))
       (and (boundp meth)
           (stringp (symbol-value meth))
           (setq mess (concat mess "; " (symbol-value meth))))
       (setq methods (cdr methods)))
-    (gnus-message 2 mess)))
+    (if arg
+       (insert (message mess))
+      (message mess))))
 
 (defun gnus-info-find-node ()
   "Find Info documentation of Gnus."
   (interactive)
   ;; Enlarge info window if needed.
-  (let ((mode major-mode))
-    (gnus-configure-windows 'info)
-    (Info-goto-node (car (cdr (assq mode gnus-info-nodes))))))
-
-(defun gnus-replace-chars-in-string (string &rest pairs)
-  "Replace characters in STRING from FROM to TO."
-  (let ((string (substring string 0))  ;Copy string.
-       (len (length string))
-       (idx 0)
-       sym to)
-    (or (zerop (% (length pairs) 2)) 
-       (error "Odd number of translation pairs"))
-    (setplist 'sym pairs)
-    ;; Replace all occurrences of FROM with TO.
-    (while (< idx len)
-      (if (setq to (get 'sym (aref string idx)))
-         (aset string idx to))
-      (setq idx (1+ idx)))
-    string))
+  (let ((mode major-mode)
+       gnus-info-buffer)
+    (Info-goto-node (cadr (assq mode gnus-info-nodes)))
+    (setq gnus-info-buffer (current-buffer))
+    (gnus-configure-windows 'info)))
 
 (defun gnus-days-between (date1 date2)
   ;; Return the number of days between date1 and date2.
@@ -3283,27 +3589,22 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
 (defun gnus-day-number (date)
   (let ((dat (mapcar (lambda (s) (and s (string-to-int s)) )
                     (timezone-parse-date date))))
-    (timezone-absolute-from-gregorian 
+    (timezone-absolute-from-gregorian
      (nth 1 dat) (nth 2 dat) (car dat))))
 
-;; Returns a floating point number that says how many seconds have
-;; lapsed between Jan 1 12:00:00 1970 and DATE.
-(defun gnus-seconds-since-epoch (date)
-  (let* ((tdate (mapcar (lambda (ti) (and ti (string-to-int ti)))
-                       (timezone-parse-date date)))
-        (ttime (mapcar (lambda (ti) (and ti (string-to-int ti)))
-                       (timezone-parse-time
-                        (aref (timezone-parse-date date) 3))))
-        (edate (mapcar (lambda (ti) (and ti (string-to-int ti)))
-                       (timezone-parse-date "Jan 1 12:00:00 1970")))
-        (tday (- (timezone-absolute-from-gregorian 
-                  (nth 1 tdate) (nth 2 tdate) (nth 0 tdate))
-                 (timezone-absolute-from-gregorian 
-                  (nth 1 edate) (nth 2 edate) (nth 0 edate)))))
-    (+ (nth 2 ttime)
-       (* (nth 1 ttime) 60)
-       (* 1.0 (nth 0 ttime) 60 60)
-       (* 1.0 tday 60 60 24))))
+(defun gnus-encode-date (date)
+  "Convert DATE to internal time."
+  (let* ((parse (timezone-parse-date date))
+        (date (mapcar (lambda (d) (and d (string-to-int d))) parse))
+        (time (mapcar 'string-to-int (timezone-parse-time (aref parse 3)))))
+    (encode-time (caddr time) (cadr time) (car time)
+                (caddr date) (cadr date) (car date) (nth 4 date))))
+
+(defun gnus-time-minus (t1 t2)
+  "Subtract two internal times."
+  (let ((borrow (< (cadr t1) (cadr t2))))
+    (list (- (car t1) (car t2) (if borrow 1 0))
+         (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
 
 (defun gnus-file-newer-than (file date)
   (let ((fdate (nth 5 (file-attributes file))))
@@ -3311,9 +3612,43 @@ If optional argument RE-ONLY is non-nil, strip `Re:' only."
        (and (= (car fdate) (car date))
             (> (nth 1 fdate) (nth 1 date))))))
 
+(defmacro gnus-local-set-keys (&rest plist)
+  "Set the keys in PLIST in the current keymap."
+  `(gnus-define-keys-1 (current-local-map) ',plist))
+
+(defmacro gnus-define-keys (keymap &rest plist)
+  "Define all keys in PLIST in KEYMAP."
+  `(gnus-define-keys-1 (quote ,keymap) (quote ,plist)))
+
+(put 'gnus-define-keys 'lisp-indent-function 1)
+(put 'gnus-define-keys 'lisp-indent-hook 1)
+(put 'gnus-define-keymap 'lisp-indent-function 1)
+(put 'gnus-define-keymap 'lisp-indent-hook 1)
+
+(defmacro gnus-define-keymap (keymap &rest plist)
+  "Define all keys in PLIST in KEYMAP."
+  `(gnus-define-keys-1 ,keymap (quote ,plist)))
+
+(defun gnus-define-keys-1 (keymap plist)
+  (when (null keymap)
+    (error "Can't set keys in a null keymap"))
+  (cond ((symbolp keymap)
+        (setq keymap (symbol-value keymap)))
+       ((keymapp keymap))
+       ((listp keymap)
+        (set (car keymap) nil)
+        (define-prefix-command (car keymap))
+        (define-key (symbol-value (caddr keymap)) (cadr keymap) (car keymap))
+        (setq keymap (symbol-value (car keymap)))))
+  (let (key)
+    (while plist
+      (when (symbolp (setq key (pop plist)))
+       (setq key (symbol-value key)))
+      (define-key keymap key (pop plist)))))
+
 (defun gnus-group-read-only-p (&optional group)
   "Check whether GROUP supports editing or not.
-If GROUP is nil, `gnus-newsgroup-name' will be checked instead.  Note
+If GROUP is nil, `gnus-newsgroup-name' will be checked instead.         Note
 that that variable is buffer-local to the summary buffers."
   (let ((group (or group gnus-newsgroup-name)))
     (not (gnus-check-backend-function 'request-replace-article group))))
@@ -3321,7 +3656,7 @@ that that variable is buffer-local to the summary buffers."
 (defun gnus-group-total-expirable-p (group)
   "Check whether GROUP is total-expirable or not."
   (let ((params (gnus-info-params (gnus-get-info group))))
-    (or (memq 'total-expire params) 
+    (or (memq 'total-expire params)
        (cdr (assq 'total-expire params)) ; (total-expire . t)
        (and gnus-total-expirable-newsgroups ; Check var.
             (string-match gnus-total-expirable-newsgroups group)))))
@@ -3329,11 +3664,22 @@ that that variable is buffer-local to the summary buffers."
 (defun gnus-group-auto-expirable-p (group)
   "Check whether GROUP is total-expirable or not."
   (let ((params (gnus-info-params (gnus-get-info group))))
-    (or (memq 'auto-expire params) 
+    (or (memq 'auto-expire params)
        (cdr (assq 'auto-expire params)) ; (auto-expire . t)
        (and gnus-auto-expirable-newsgroups ; Check var.
             (string-match gnus-auto-expirable-newsgroups group)))))
 
+(defun gnus-virtual-group-p (group)
+  "Say whether GROUP is virtual or not."
+  (memq 'virtual (assoc (symbol-name (car (gnus-find-method-for-group group)))
+                       gnus-valid-select-methods)))
+
+(defun gnus-news-group-p (group &optional article)
+  "Return non-nil if GROUP (and ARTICLE) come from a news server."
+  (or (gnus-member-of-valid 'post group) ; Ordinary news group.
+      (and (gnus-member-of-valid 'post-mail group) ; Combined group.
+          (eq (gnus-request-type group article) 'news))))
+
 (defsubst gnus-simplify-subject-fully (subject)
   "Simplify a subject string according to the user's wishes."
   (cond
@@ -3342,11 +3688,12 @@ that that variable is buffer-local to the summary buffers."
    ((eq gnus-summary-gather-subject-limit 'fuzzy)
     (gnus-simplify-subject-fuzzy subject))
    ((numberp gnus-summary-gather-subject-limit)
-    (gnus-limit-string subject gnus-summary-gather-subject-limit))
+    (gnus-limit-string (gnus-simplify-subject-re subject)
+                      gnus-summary-gather-subject-limit))
    (t
     subject)))
 
-(defsubst gnus-subject-equal (s1 s2 &optional simple-first) 
+(defsubst gnus-subject-equal (s1 s2 &optional simple-first)
   "Check whether two subjects are equal.  If optional argument
 simple-first is t, first argument is already simplified."
   (cond
@@ -3360,13 +3707,22 @@ simple-first is t, first argument is already simplified."
 ;; Returns a list of writable groups.
 (defun gnus-writable-groups ()
   (let ((alist gnus-newsrc-alist)
-       groups)
-    (while alist
-      (or (gnus-group-read-only-p (car (car alist)))
-         (setq groups (cons (car (car alist)) groups)))
-      (setq alist (cdr alist)))
+       groups group)
+    (while (setq group (car (pop alist)))
+      (unless (gnus-group-read-only-p group)
+       (push group groups)))
     (nreverse groups)))
 
+(defun gnus-completing-read (default prompt &rest args)
+  ;; Like `completing-read', except that DEFAULT is the default argument.
+  (let* ((prompt (if default 
+                    (concat prompt " (default " default ") ")
+                  (concat prompt " ")))
+        (answer (apply 'completing-read prompt args)))
+    (if (or (null answer) (zerop (length answer)))
+       default
+      answer)))
+
 ;; Two silly functions to ensure that all `y-or-n-p' questions clear
 ;; the echo area.
 (defun gnus-y-or-n-p (prompt)
@@ -3386,21 +3742,37 @@ simple-first is t, first argument is already simplified."
        ;; If it isn't a list, then we return t.
        (or (not (listp gnus-use-long-file-name))
           ;; If it is a list, and the list contains `symbol', we
-          ;; return nil.  
+          ;; return nil.
           (not (memq symbol gnus-use-long-file-name)))))
 
 ;; I suspect there's a better way, but I haven't taken the time to do
 ;; it yet. -erik selberg@cs.washington.edu
 (defun gnus-dd-mmm (messy-date)
   "Return a string like DD-MMM from a big messy string"
-  (let ((datevec (timezone-parse-date messy-date)))
-    (format "%2s-%s"
-           (or (aref datevec 2) "??")
-           (capitalize
-            (or (car 
-                 (nth (1- (string-to-number (aref datevec 1)))
-                      timezone-months-assoc))
-                "???")))))
+  (let ((datevec (condition-case () (timezone-parse-date messy-date) 
+                  (error nil))))
+    (if (not datevec)
+       "??-???"
+      (format "%2s-%s"
+             (condition-case ()
+                 ;; Make sure leading zeroes are stripped.
+                 (number-to-string (string-to-number (aref datevec 2)))
+               (error "??"))
+             (capitalize
+              (or (car
+                   (nth (1- (string-to-number (aref datevec 1)))
+                        timezone-months-assoc))
+                  "???"))))))
+
+(defun gnus-mode-string-quote (string)
+  "Quote all \"%\" in STRING."
+  (save-excursion
+    (gnus-set-work-buffer)
+    (insert string)
+    (goto-char (point-min))
+    (while (search-forward "%" nil t)
+      (insert "%"))
+    (buffer-string)))
 
 ;; Make a hash table (default and minimum size is 255).
 ;; Optional argument HASHSIZE specifies the table size.
@@ -3415,23 +3787,29 @@ simple-first is t, first argument is already simplified."
       (setq i (* 2 i)))
     (1- i)))
 
-;; Show message if message has a lower level than `gnus-verbose'. 
-;; Guide-line for numbers:
+;; Show message if message has a lower level than `gnus-verbose'.
+;; Guideline for numbers:
 ;; 1 - error messages, 3 - non-serious error messages, 5 - messages
 ;; for things that take a long time, 7 - not very important messages
 ;; on stuff, 9 - messages inside loops.
 (defun gnus-message (level &rest args)
   (if (<= level gnus-verbose)
       (apply 'message args)
-    ;; We have to do this format thingie here even if the result isn't
+    ;; We have to do this format thingy here even if the result isn't
     ;; shown - the return value has to be the same as the return value
     ;; from `message'.
     (apply 'format args)))
 
-(defun gnus-functionp (form)
-  "Return non-nil if FORM is funcallable."
-  (or (and (symbolp form) (fboundp form))
-      (and (listp form) (eq (car form) 'lambda))))
+(defun gnus-error (level &rest args)
+  "Beep an error if `gnus-verbose' is on LEVEL or less."
+  (when (<= (floor level) gnus-verbose)
+    (apply 'message args)
+    (ding)
+    (let (duration)
+      (when (and (floatp level)
+                (not (zerop (setq duration (* 10 (- level (floor level)))))))
+       (sit-for duration))))
+  nil)
 
 ;; Generate a unique new group name.
 (defun gnus-generate-new-group-name (leaf)
@@ -3441,29 +3819,65 @@ simple-first is t, first argument is already simplified."
       (setq name (concat leaf "<" (int-to-string (setq num (1+ num))) ">")))
     name))
 
-;; Find out whether the gnus-visual TYPE is wanted.
-(defun gnus-visual-p (&optional type class)
-  (and gnus-visual                     ; Has to be non-nil, at least.
-       (if (not type)                  ; We don't care about type.
-          gnus-visual
-        (if (listp gnus-visual)        ; It's a list, so we check it.
-            (or (memq type gnus-visual)
-                (memq class gnus-visual))
-          t))))
+(defsubst gnus-hide-text (b e props)
+  "Set text PROPS on the B to E region, extending `intangible' 1 past B."
+  (gnus-add-text-properties b e props)
+  (when (memq 'intangible props)
+    (gnus-put-text-property (max (1- b) (point-min))
+                      b 'intangible (cddr (memq 'intangible props)))))
+
+(defsubst gnus-unhide-text (b e)
+  "Remove hidden text properties from region between B and E."
+  (remove-text-properties b e gnus-hidden-properties)
+  (when (memq 'intangible gnus-hidden-properties)
+    (gnus-put-text-property (max (1- b) (point-min))
+                           b 'intangible nil)))
+
+(defun gnus-hide-text-type (b e type)
+  "Hide text of TYPE between B and E."
+  (gnus-hide-text b e (cons 'gnus-type (cons type gnus-hidden-properties))))
+
+(defun gnus-parent-headers (headers &optional generation)
+  "Return the headers of the GENERATIONeth parent of HEADERS."
+  (unless generation 
+    (setq generation 1))
+  (let (references parent)
+    (while (and headers (not (zerop generation)))
+      (setq references (mail-header-references headers))
+      (when (and references
+                (setq parent (gnus-parent-id references))
+                (setq headers (car (gnus-id-to-thread parent))))
+       (decf generation)))
+    headers))
 
 (defun gnus-parent-id (references)
   "Return the last Message-ID in REFERENCES."
-  (and references
-       (string-match "\\(<[^<>]+>\\) *$" references)
-       (substring references (match-beginning 1) (match-end 1))))
+  (when (and references
+            (string-match "\\(<[^\n<>]+>\\)[ \t\n]*\\'" references))
+    (substring references (match-beginning 1) (match-end 1))))
+
+(defun gnus-split-references (references)
+  "Return a list of Message-IDs in REFERENCES."
+  (let ((beg 0)
+       ids)
+    (while (string-match "<[^>]+>" references beg)
+      (push (substring references (match-beginning 0) (setq beg (match-end 0)))
+           ids))
+    (nreverse ids)))
+
+(defun gnus-buffer-live-p (buffer)
+  "Say whether BUFFER is alive or not."
+  (and buffer
+       (get-buffer buffer)
+       (buffer-name (get-buffer buffer))))
 
 (defun gnus-ephemeral-group-p (group)
   "Say whether GROUP is ephemeral or not."
-  (assoc 'quit-config (gnus-find-method-for-group group)))
+  (gnus-group-get-parameter group 'quit-config))
 
 (defun gnus-group-quit-config (group)
   "Return the quit-config of GROUP."
-  (nth 1 (assoc 'quit-config (gnus-find-method-for-group group))))
+  (gnus-group-get-parameter group 'quit-config))
 
 (defun gnus-simplify-mode-line ()
   "Make mode lines a bit simpler."
@@ -3471,8 +3885,8 @@ simple-first is t, first argument is already simplified."
   (when (listp mode-line-format)
     (make-local-variable 'mode-line-format)
     (setq mode-line-format (copy-sequence mode-line-format))
-    (and (equal (nth 3 mode-line-format) "   ")
-        (setcar (nthcdr 3 mode-line-format) ""))))
+    (when (equal (nth 3 mode-line-format) "   ")
+      (setcar (nthcdr 3 mode-line-format) " "))))
 
 ;;; List and range functions
 
@@ -3486,7 +3900,7 @@ simple-first is t, first argument is already simplified."
   "Do a complete, total copy of a list."
   (if (and (consp list) (not (consp (cdr list))))
       (cons (car list) (cdr list))
-    (mapcar (lambda (elem) (if (consp elem) 
+    (mapcar (lambda (elem) (if (consp elem)
                               (if (consp (cdr elem))
                                   (gnus-copy-sequence elem)
                                 (cons (car elem) (cdr elem)))
@@ -3519,7 +3933,7 @@ Both lists have to be sorted over <."
               (setq list2 (cdr list2)))))
       (nconc (nreverse out) (or list1 list2)))))
 
-(defun gnus-intersection (list1 list2)      
+(defun gnus-intersection (list1 list2)
   (let ((result nil))
     (while list2
       (if (memq (car list2) list1)
@@ -3575,7 +3989,7 @@ ranges."
                ((= (1+ last) (car numbers)) ;Still in sequence
                 (setq last (car numbers)))
                (t                      ;End of one sequence
-                (setq result 
+                (setq result
                       (cons (if (= first last) first
                               (cons first last)) result))
                 (setq first (car numbers))
@@ -3592,7 +4006,7 @@ ranges."
 RANGES is either a single range on the form `(num . num)' or a list of
 these ranges."
   (let (first last result)
-    (cond 
+    (cond
      ((null ranges)
       nil)
      ((not (listp (cdr ranges)))
@@ -3607,8 +4021,8 @@ these ranges."
        (if (atom (car ranges))
            (if (numberp (car ranges))
                (setq result (cons (car ranges) result)))
-         (setq first (car (car ranges)))
-         (setq last  (cdr (car ranges)))
+         (setq first (caar ranges))
+         (setq last  (cdar ranges))
          (while (<= first last)
            (setq result (cons first result))
            (setq first (1+ first))))
@@ -3628,8 +4042,8 @@ Note: LIST has to be sorted over `<'."
       (while (and ranges list)
        (setq ilist list)
        (setq lowest (or (and (atom (car ranges)) (car ranges))
-                        (car (car ranges))))
-       (while (and list (cdr list) (< (car (cdr list)) lowest))
+                        (caar ranges)))
+       (while (and list (cdr list) (< (cadr list) lowest))
          (setq list (cdr list)))
        (if (< (car ilist) lowest)
            (progn
@@ -3638,40 +4052,40 @@ Note: LIST has to be sorted over `<'."
              (setcdr temp nil)
              (setq out (nconc (gnus-compress-sequence ilist t) out))))
        (setq highest (or (and (atom (car ranges)) (car ranges))
-                         (cdr (car ranges))))
+                         (cdar ranges)))
        (while (and list (<= (car list) highest))
          (setq list (cdr list)))
        (setq ranges (cdr ranges)))
       (if list
          (setq out (nconc (gnus-compress-sequence list t) out)))
-      (setq out (sort out (lambda (r1 r2) 
+      (setq out (sort out (lambda (r1 r2)
                            (< (or (and (atom r1) r1) (car r1))
                               (or (and (atom r2) r2) (car r2))))))
       (setq ranges out)
       (while ranges
        (if (atom (car ranges))
            (if (cdr ranges)
-               (if (atom (car (cdr ranges)))
-                   (if (= (1+ (car ranges)) (car (cdr ranges)))
+               (if (atom (cadr ranges))
+                   (if (= (1+ (car ranges)) (cadr ranges))
                        (progn
-                         (setcar ranges (cons (car ranges) 
-                                              (car (cdr ranges))))
-                         (setcdr ranges (cdr (cdr ranges)))))
-                 (if (= (1+ (car ranges)) (car (car (cdr ranges))))
+                         (setcar ranges (cons (car ranges)
+                                              (cadr ranges)))
+                         (setcdr ranges (cddr ranges))))
+                 (if (= (1+ (car ranges)) (caadr ranges))
                      (progn
-                       (setcar (car (cdr ranges)) (car ranges))
-                       (setcar ranges (car (cdr ranges)))
-                       (setcdr ranges (cdr (cdr ranges)))))))
+                       (setcar (cadr ranges) (car ranges))
+                       (setcar ranges (cadr ranges))
+                       (setcdr ranges (cddr ranges))))))
          (if (cdr ranges)
-             (if (atom (car (cdr ranges)))
-                 (if (= (1+ (cdr (car ranges))) (car (cdr ranges)))
+             (if (atom (cadr ranges))
+                 (if (= (1+ (cdar ranges)) (cadr ranges))
                      (progn
-                       (setcdr (car ranges) (car (cdr ranges)))
-                       (setcdr ranges (cdr (cdr ranges)))))
-               (if (= (1+ (cdr (car ranges))) (car (car (cdr ranges))))
+                       (setcdr (car ranges) (cadr ranges))
+                       (setcdr ranges (cddr ranges))))
+               (if (= (1+ (cdar ranges)) (caadr ranges))
                    (progn
-                     (setcdr (car ranges) (cdr (car (cdr ranges))))
-                     (setcdr ranges (cdr (cdr ranges))))))))
+                     (setcdr (car ranges) (cdadr ranges))
+                     (setcdr ranges (cddr ranges)))))))
        (setq ranges (cdr ranges)))
       out)))
 
@@ -3679,24 +4093,24 @@ Note: LIST has to be sorted over `<'."
   "Return a list of ranges that has all articles from LIST removed from RANGES.
 Note: LIST has to be sorted over `<'."
   ;; !!! This function shouldn't look like this, but I've got a headache.
-  (gnus-compress-sequence 
+  (gnus-compress-sequence
    (gnus-sorted-complement
     (gnus-uncompress-range ranges) list)))
 
 (defun gnus-member-of-range (number ranges)
   (if (not (listp (cdr ranges)))
-      (and (>= number (car ranges)) 
+      (and (>= number (car ranges))
           (<= number (cdr ranges)))
     (let ((not-stop t))
-      (while (and ranges 
+      (while (and ranges
                  (if (numberp (car ranges))
                      (>= number (car ranges))
-                   (>= number (car (car ranges))))
+                   (>= number (caar ranges)))
                  not-stop)
        (if (if (numberp (car ranges))
                (= number (car ranges))
-             (and (>= number (car (car ranges)))
-                  (<= number (cdr (car ranges)))))
+             (and (>= number (caar ranges))
+                  (<= number (cdar ranges))))
            (setq not-stop nil))
        (setq ranges (cdr ranges)))
       (not not-stop))))
@@ -3720,172 +4134,159 @@ Note: LIST has to be sorted over `<'."
 ;;;
 
 (defvar gnus-group-mode-map nil)
-(defvar gnus-group-group-map nil)
-(defvar gnus-group-mark-map nil)
-(defvar gnus-group-list-map nil)
-(defvar gnus-group-sort-map nil)
-(defvar gnus-group-soup-map nil)
-(defvar gnus-group-sub-map nil)
-(defvar gnus-group-help-map nil)
-(defvar gnus-group-score-map nil)
 (put 'gnus-group-mode 'mode-class 'special)
 
-(if gnus-group-mode-map
-    nil
+(unless gnus-group-mode-map
   (setq gnus-group-mode-map (make-keymap))
   (suppress-keymap gnus-group-mode-map)
-  (define-key gnus-group-mode-map " " 'gnus-group-read-group)
-  (define-key gnus-group-mode-map "=" 'gnus-group-select-group)
-  (define-key gnus-group-mode-map "\M- " 'gnus-group-unhidden-select-group)
-  (define-key gnus-group-mode-map "\r" 'gnus-group-select-group)
-  (define-key gnus-group-mode-map "\M-\r" 'gnus-group-quick-select-group)
-  (define-key gnus-group-mode-map "j" 'gnus-group-jump-to-group)
-  (define-key gnus-group-mode-map "n" 'gnus-group-next-unread-group)
-  (define-key gnus-group-mode-map "p" 'gnus-group-prev-unread-group)
-  (define-key gnus-group-mode-map "\177" 'gnus-group-prev-unread-group)
-  (define-key gnus-group-mode-map "N" 'gnus-group-next-group)
-  (define-key gnus-group-mode-map "P" 'gnus-group-prev-group)
-  (define-key gnus-group-mode-map
-    "\M-n" 'gnus-group-next-unread-group-same-level)
-  (define-key gnus-group-mode-map 
-    "\M-p" 'gnus-group-prev-unread-group-same-level)
-  (define-key gnus-group-mode-map "," 'gnus-group-best-unread-group)
-  (define-key gnus-group-mode-map "." 'gnus-group-first-unread-group)
-  (define-key gnus-group-mode-map "u" 'gnus-group-unsubscribe-current-group)
-  (define-key gnus-group-mode-map "U" 'gnus-group-unsubscribe-group)
-  (define-key gnus-group-mode-map "c" 'gnus-group-catchup-current)
-  (define-key gnus-group-mode-map "C" 'gnus-group-catchup-current-all)
-  (define-key gnus-group-mode-map "l" 'gnus-group-list-groups)
-  (define-key gnus-group-mode-map "L" 'gnus-group-list-all-groups)
-  (define-key gnus-group-mode-map "m" 'gnus-group-mail)
-  (define-key gnus-group-mode-map "g" 'gnus-group-get-new-news)
-  (define-key gnus-group-mode-map "\M-g" 'gnus-group-get-new-news-this-group)
-  (define-key gnus-group-mode-map "R" 'gnus-group-restart)
-  (define-key gnus-group-mode-map "r" 'gnus-group-read-init-file)
-  (define-key gnus-group-mode-map "B" 'gnus-group-browse-foreign-server)
-  (define-key gnus-group-mode-map "b" 'gnus-group-check-bogus-groups)
-  (define-key gnus-group-mode-map "F" 'gnus-find-new-newsgroups)
-  (define-key gnus-group-mode-map "\C-c\C-d" 'gnus-group-describe-group)
-  (define-key gnus-group-mode-map "\M-d" 'gnus-group-describe-all-groups)
-  (define-key gnus-group-mode-map "\C-c\C-a" 'gnus-group-apropos)
-  (define-key gnus-group-mode-map "\C-c\M-\C-a" 'gnus-group-description-apropos)
-  (define-key gnus-group-mode-map "a" 'gnus-group-post-news)
-  (define-key gnus-group-mode-map "\ek" 'gnus-group-edit-local-kill)
-  (define-key gnus-group-mode-map "\eK" 'gnus-group-edit-global-kill)
-  (define-key gnus-group-mode-map "\C-k" 'gnus-group-kill-group)
-  (define-key gnus-group-mode-map "\C-y" 'gnus-group-yank-group)
-  (define-key gnus-group-mode-map "\C-w" 'gnus-group-kill-region)
-  (define-key gnus-group-mode-map "\C-x\C-t" 'gnus-group-transpose-groups)
-  (define-key gnus-group-mode-map "\C-c\C-l" 'gnus-group-list-killed)
-  (define-key gnus-group-mode-map "\C-c\C-x" 'gnus-group-expire-articles)
-  (define-key gnus-group-mode-map "\C-c\M-\C-x" 'gnus-group-expire-all-groups)
-  (define-key gnus-group-mode-map "V" 'gnus-version)
-  (define-key gnus-group-mode-map "s" 'gnus-group-save-newsrc)
-  (define-key gnus-group-mode-map "z" 'gnus-group-suspend)
-  (define-key gnus-group-mode-map "Z" 'gnus-group-clear-dribble)
-  (define-key gnus-group-mode-map "q" 'gnus-group-exit)
-  (define-key gnus-group-mode-map "Q" 'gnus-group-quit)
-  (define-key gnus-group-mode-map "?" 'gnus-group-describe-briefly)
-  (define-key gnus-group-mode-map "\C-c\C-i" 'gnus-info-find-node)
-  (define-key gnus-group-mode-map "\M-e" 'gnus-group-edit-group-method)
-  (define-key gnus-group-mode-map "^" 'gnus-group-enter-server-mode)
-  (define-key gnus-group-mode-map gnus-mouse-2 'gnus-mouse-pick-group)
-  (define-key gnus-group-mode-map "<" 'beginning-of-buffer)
-  (define-key gnus-group-mode-map ">" 'end-of-buffer)
-  (define-key gnus-group-mode-map "\C-c\C-b" 'gnus-bug)
-  (define-key gnus-group-mode-map "\C-c\C-s" 'gnus-group-sort-groups)
-  (define-key gnus-group-mode-map "t" 'gnus-topic-mode)
-  (define-key gnus-group-mode-map "\C-c\M-g" 'gnus-activate-all-groups)
-
-  (define-key gnus-group-mode-map "#" 'gnus-group-mark-group)
-  (define-key gnus-group-mode-map "\M-#" 'gnus-group-unmark-group)
-  (define-prefix-command 'gnus-group-mark-map)
-  (define-key gnus-group-mode-map "M" 'gnus-group-mark-map)
-  (define-key gnus-group-mark-map "m" 'gnus-group-mark-group)
-  (define-key gnus-group-mark-map "u" 'gnus-group-unmark-group)
-  (define-key gnus-group-mark-map "w" 'gnus-group-mark-region)
-  (define-key gnus-group-mark-map "r" 'gnus-group-mark-regexp)
-
-  (define-prefix-command 'gnus-group-group-map)
-  (define-key gnus-group-mode-map "G" 'gnus-group-group-map)
-  (define-key gnus-group-group-map "d" 'gnus-group-make-directory-group)
-  (define-key gnus-group-group-map "h" 'gnus-group-make-help-group)
-  (define-key gnus-group-group-map "a" 'gnus-group-make-archive-group)
-  (define-key gnus-group-group-map "k" 'gnus-group-make-kiboze-group)
-  (define-key gnus-group-group-map "m" 'gnus-group-make-group)
-  (define-key gnus-group-group-map "E" 'gnus-group-edit-group)
-  (define-key gnus-group-group-map "e" 'gnus-group-edit-group-method)
-  (define-key gnus-group-group-map "p" 'gnus-group-edit-group-parameters)
-  (define-key gnus-group-group-map "v" 'gnus-group-add-to-virtual)
-  (define-key gnus-group-group-map "V" 'gnus-group-make-empty-virtual)
-  (define-key gnus-group-group-map "D" 'gnus-group-enter-directory)
-  (define-key gnus-group-group-map "f" 'gnus-group-make-doc-group)
-  (define-key gnus-group-group-map "r" 'gnus-group-rename-group)
-  (define-key gnus-group-group-map "\177" 'gnus-group-delete-group)
-
-  (define-prefix-command 'gnus-group-soup-map)
-  (define-key gnus-group-group-map "s" 'gnus-group-soup-map)
-  (define-key gnus-group-soup-map "b" 'gnus-group-brew-soup)
-  (define-key gnus-group-soup-map "w" 'gnus-soup-save-areas)
-  (define-key gnus-group-soup-map "s" 'gnus-soup-send-replies)
-  (define-key gnus-group-soup-map "p" 'gnus-soup-pack-packet)
-  (define-key gnus-group-soup-map "r" 'nnsoup-pack-replies)
-
-  (define-prefix-command 'gnus-group-sort-map)
-  (define-key gnus-group-group-map "S" 'gnus-group-sort-map)
-  (define-key gnus-group-sort-map "s" 'gnus-group-sort-groups)
-  (define-key gnus-group-sort-map "a" 'gnus-group-sort-groups-by-alphabet)
-  (define-key gnus-group-sort-map "u" 'gnus-group-sort-groups-by-unread)
-  (define-key gnus-group-sort-map "l" 'gnus-group-sort-groups-by-level)
-  (define-key gnus-group-sort-map "v" 'gnus-group-sort-groups-by-score)
-  (define-key gnus-group-sort-map "r" 'gnus-group-sort-groups-by-rank)
-  (define-key gnus-group-sort-map "m" 'gnus-group-sort-groups-by-method)
-
-  (define-prefix-command 'gnus-group-list-map)
-  (define-key gnus-group-mode-map "A" 'gnus-group-list-map)
-  (define-key gnus-group-list-map "k" 'gnus-group-list-killed)
-  (define-key gnus-group-list-map "z" 'gnus-group-list-zombies)
-  (define-key gnus-group-list-map "s" 'gnus-group-list-groups)
-  (define-key gnus-group-list-map "u" 'gnus-group-list-all-groups)
-  (define-key gnus-group-list-map "A" 'gnus-group-list-active)
-  (define-key gnus-group-list-map "a" 'gnus-group-apropos)
-  (define-key gnus-group-list-map "d" 'gnus-group-description-apropos)
-  (define-key gnus-group-list-map "m" 'gnus-group-list-matching)
-  (define-key gnus-group-list-map "M" 'gnus-group-list-all-matching)
-  (define-key gnus-group-list-map "l" 'gnus-group-list-level)
-
-  (define-prefix-command 'gnus-group-score-map)
-  (define-key gnus-group-mode-map "W" 'gnus-group-score-map)
-  (define-key gnus-group-score-map "f" 'gnus-score-flush-cache)
-
-  (define-prefix-command 'gnus-group-help-map)
-  (define-key gnus-group-mode-map "H" 'gnus-group-help-map)
-  (define-key gnus-group-help-map "f" 'gnus-group-fetch-faq)
-
-  (define-prefix-command 'gnus-group-sub-map)
-  (define-key gnus-group-mode-map "S" 'gnus-group-sub-map)
-  (define-key gnus-group-sub-map "l" 'gnus-group-set-current-level)
-  (define-key gnus-group-sub-map "t" 'gnus-group-unsubscribe-current-group)
-  (define-key gnus-group-sub-map "s" 'gnus-group-unsubscribe-group)
-  (define-key gnus-group-sub-map "k" 'gnus-group-kill-group)
-  (define-key gnus-group-sub-map "y" 'gnus-group-yank-group)
-  (define-key gnus-group-sub-map "w" 'gnus-group-kill-region)
-  (define-key gnus-group-sub-map "\C-k" 'gnus-group-kill-level)
-  (define-key gnus-group-sub-map "z" 'gnus-group-kill-all-zombies))
+
+  (gnus-define-keys gnus-group-mode-map
+    " " gnus-group-read-group
+    "=" gnus-group-select-group
+    "\r" gnus-group-select-group
+    "\M-\r" gnus-group-quick-select-group
+    "j" gnus-group-jump-to-group
+    "n" gnus-group-next-unread-group
+    "p" gnus-group-prev-unread-group
+    "\177" gnus-group-prev-unread-group
+    [delete] gnus-group-prev-unread-group
+    "N" gnus-group-next-group
+    "P" gnus-group-prev-group
+    "\M-n" gnus-group-next-unread-group-same-level
+    "\M-p" gnus-group-prev-unread-group-same-level
+    "," gnus-group-best-unread-group
+    "." gnus-group-first-unread-group
+    "u" gnus-group-unsubscribe-current-group
+    "U" gnus-group-unsubscribe-group
+    "c" gnus-group-catchup-current
+    "C" gnus-group-catchup-current-all
+    "l" gnus-group-list-groups
+    "L" gnus-group-list-all-groups
+    "m" gnus-group-mail
+    "g" gnus-group-get-new-news
+    "\M-g" gnus-group-get-new-news-this-group
+    "R" gnus-group-restart
+    "r" gnus-group-read-init-file
+    "B" gnus-group-browse-foreign-server
+    "b" gnus-group-check-bogus-groups
+    "F" gnus-find-new-newsgroups
+    "\C-c\C-d" gnus-group-describe-group
+    "\M-d" gnus-group-describe-all-groups
+    "\C-c\C-a" gnus-group-apropos
+    "\C-c\M-\C-a" gnus-group-description-apropos
+    "a" gnus-group-post-news
+    "\ek" gnus-group-edit-local-kill
+    "\eK" gnus-group-edit-global-kill
+    "\C-k" gnus-group-kill-group
+    "\C-y" gnus-group-yank-group
+    "\C-w" gnus-group-kill-region
+    "\C-x\C-t" gnus-group-transpose-groups
+    "\C-c\C-l" gnus-group-list-killed
+    "\C-c\C-x" gnus-group-expire-articles
+    "\C-c\M-\C-x" gnus-group-expire-all-groups
+    "V" gnus-version
+    "s" gnus-group-save-newsrc
+    "z" gnus-group-suspend
+    "Z" gnus-group-clear-dribble
+    "q" gnus-group-exit
+    "Q" gnus-group-quit
+    "?" gnus-group-describe-briefly
+    "\C-c\C-i" gnus-info-find-node
+    "\M-e" gnus-group-edit-group-method
+    "^" gnus-group-enter-server-mode
+    gnus-mouse-2 gnus-mouse-pick-group
+    "<" beginning-of-buffer
+    ">" end-of-buffer
+    "\C-c\C-b" gnus-bug
+    "\C-c\C-s" gnus-group-sort-groups
+    "t" gnus-topic-mode
+    "\C-c\M-g" gnus-activate-all-groups
+    "\M-&" gnus-group-universal-argument
+    "#" gnus-group-mark-group
+    "\M-#" gnus-group-unmark-group)
+
+  (gnus-define-keys (gnus-group-mark-map "M" gnus-group-mode-map)
+    "m" gnus-group-mark-group
+    "u" gnus-group-unmark-group
+    "w" gnus-group-mark-region
+    "m" gnus-group-mark-buffer
+    "r" gnus-group-mark-regexp
+    "U" gnus-group-unmark-all-groups)
+
+  (gnus-define-keys (gnus-group-group-map "G" gnus-group-mode-map)
+    "d" gnus-group-make-directory-group
+    "h" gnus-group-make-help-group
+    "a" gnus-group-make-archive-group
+    "k" gnus-group-make-kiboze-group
+    "m" gnus-group-make-group
+    "E" gnus-group-edit-group
+    "e" gnus-group-edit-group-method
+    "p" gnus-group-edit-group-parameters
+    "v" gnus-group-add-to-virtual
+    "V" gnus-group-make-empty-virtual
+    "D" gnus-group-enter-directory
+    "f" gnus-group-make-doc-group
+    "r" gnus-group-rename-group
+    "\177" gnus-group-delete-group
+    [delete] gnus-group-delete-group)
+
+   (gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map)
+     "b" gnus-group-brew-soup
+     "w" gnus-soup-save-areas
+     "s" gnus-soup-send-replies
+     "p" gnus-soup-pack-packet
+     "r" nnsoup-pack-replies)
+
+   (gnus-define-keys (gnus-group-sort-map "S" gnus-group-group-map)
+     "s" gnus-group-sort-groups
+     "a" gnus-group-sort-groups-by-alphabet
+     "u" gnus-group-sort-groups-by-unread
+     "l" gnus-group-sort-groups-by-level
+     "v" gnus-group-sort-groups-by-score
+     "r" gnus-group-sort-groups-by-rank
+     "m" gnus-group-sort-groups-by-method)
+
+   (gnus-define-keys (gnus-group-list-map "A" gnus-group-mode-map)
+     "k" gnus-group-list-killed
+     "z" gnus-group-list-zombies
+     "s" gnus-group-list-groups
+     "u" gnus-group-list-all-groups
+     "A" gnus-group-list-active
+     "a" gnus-group-apropos
+     "d" gnus-group-description-apropos
+     "m" gnus-group-list-matching
+     "M" gnus-group-list-all-matching
+     "l" gnus-group-list-level)
+
+   (gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map)
+     "f" gnus-score-flush-cache)
+
+   (gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map)
+     "f" gnus-group-fetch-faq)
+
+   (gnus-define-keys (gnus-group-sub-map "S" gnus-group-mode-map)
+     "l" gnus-group-set-current-level
+     "t" gnus-group-unsubscribe-current-group
+     "s" gnus-group-unsubscribe-group
+     "k" gnus-group-kill-group
+     "y" gnus-group-yank-group
+     "w" gnus-group-kill-region
+     "\C-k" gnus-group-kill-level
+     "z" gnus-group-kill-all-zombies))
 
 (defun gnus-group-mode ()
   "Major mode for reading news.
 
 All normal editing commands are switched off.
 \\<gnus-group-mode-map>
-The group buffer lists (some of) the groups available.  For instance,
+The group buffer lists (some of) the groups available. For instance,
 `\\[gnus-group-list-groups]' will list all subscribed groups with unread articles, while `\\[gnus-group-list-zombies]'
-lists all zombie groups. 
+lists all zombie groups.
 
-Groups that are displayed can be entered with `\\[gnus-group-read-group]'.  To subscribe 
-to a group not displayed, type `\\[gnus-group-unsubscribe-group]'. 
+Groups that are displayed can be entered with `\\[gnus-group-read-group]'.  To subscribe
+to a group not displayed, type `\\[gnus-group-unsubscribe-group]'.
 
-For more in-depth information on this mode, read the manual (`\\[gnus-info-find-node]'). 
+For more in-depth information on this mode, read the manual (`\\[gnus-info-find-node]').
 
 The following commands are available:
 
@@ -3904,8 +4305,13 @@ The following commands are available:
   (buffer-disable-undo (current-buffer))
   (setq truncate-lines t)
   (setq buffer-read-only t)
+  (gnus-make-local-hook 'post-command-hook)
+  (gnus-add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
   (run-hooks 'gnus-group-mode-hook))
 
+(defun gnus-clear-inboxes-moved ()
+  (setq nnmail-moved-inboxes nil))
+
 (defun gnus-mouse-pick-group (e)
   "Enter the group under the mouse pointer."
   (interactive "e")
@@ -3916,16 +4322,19 @@ The following commands are available:
 ;; If LEVEL is non-nil, LEVEL will be returned, if not, what happens
 ;; will depend on whether `gnus-group-use-permanent-levels' is used.
 (defun gnus-group-default-level (&optional level number-or-nil)
-  (cond  
+  (cond
    (gnus-group-use-permanent-levels
-    (setq gnus-group-default-list-level 
-         (or level gnus-group-default-list-level))
-    (or gnus-group-default-list-level gnus-level-subscribed))
+    (or (setq gnus-group-use-permanent-levels
+             (or level (if (numberp gnus-group-use-permanent-levels)
+                           gnus-group-use-permanent-levels
+                         (or gnus-group-default-list-level
+                             gnus-level-subscribed))))
+       gnus-group-default-list-level gnus-level-subscribed))
    (number-or-nil
     level)
    (t
     (or level gnus-group-default-list-level gnus-level-subscribed))))
-  
+
 ;;;###autoload
 (defun gnus-slave-no-server (&optional arg)
   "Read network news as a slave, without connecting to local server"
@@ -3936,14 +4345,15 @@ The following commands are available:
 (defun gnus-no-server (&optional arg slave)
   "Read network news.
 If ARG is a positive number, Gnus will use that as the
-startup level.  If ARG is nil, Gnus will be started at level 2. 
+startup level. If ARG is nil, Gnus will be started at level 2.
 If ARG is non-nil and not a positive number, Gnus will
 prompt the user for the name of an NNTP server to use.
 As opposed to `gnus', this command will not connect to the local server."
   (interactive "P")
-  (make-local-variable 'gnus-group-use-permanent-levels)
-  (setq gnus-group-use-permanent-levels t)
-  (gnus (or arg (1- gnus-level-default-subscribed)) t slave))
+  (let ((val (or arg (1- gnus-level-default-subscribed))))
+    (gnus val t slave)
+    (make-local-variable 'gnus-group-use-permanent-levels)
+    (setq gnus-group-use-permanent-levels val)))
 
 ;;;###autoload
 (defun gnus-slave (&optional arg)
@@ -3951,13 +4361,24 @@ As opposed to `gnus', this command will not connect to the local server."
   (interactive "P")
   (gnus arg nil 'slave))
 
+;;;###autoload
+(defun gnus-other-frame (&optional arg)
+  "Pop up a frame to read news."
+  (interactive "P")
+  (if (get-buffer gnus-group-buffer)
+      (let ((pop-up-frames t))
+       (gnus arg))
+    (select-frame (make-frame))
+    (gnus arg)))
+
 ;;;###autoload
 (defun gnus (&optional arg dont-connect slave)
   "Read network news.
 If ARG is non-nil and a positive number, Gnus will use that as the
-startup level.  If ARG is non-nil and not a positive number, Gnus will
+startup level. If ARG is non-nil and not a positive number, Gnus will
 prompt the user for the name of an NNTP server to use."
   (interactive "P")
+
   (if (get-buffer gnus-group-buffer)
       (progn
        (switch-to-buffer gnus-group-buffer)
@@ -3975,32 +4396,39 @@ prompt the user for the name of an NNTP server to use."
          (progn
            (gnus-group-startup-message)
            (sit-for 0))))
-    
-    (let ((level (and arg (numberp arg) (> arg 0) arg))
+
+    (let ((level (and (numberp arg) (> arg 0) arg))
          did-connect)
       (unwind-protect
          (progn
-           (or dont-connect 
+           (or dont-connect
                (setq did-connect
                      (gnus-start-news-server (and arg (not level))))))
-       (if (and (not dont-connect) 
+       (if (and (not dont-connect)
                 (not did-connect))
            (gnus-group-quit)
          (run-hooks 'gnus-startup-hook)
-         ;; NNTP server is successfully open. 
+         ;; NNTP server is successfully open.
 
          ;; Find the current startup file name.
-         (setq gnus-current-startup-file 
+         (setq gnus-current-startup-file
                (gnus-make-newsrc-file gnus-startup-file))
 
          ;; Read the dribble file.
-         (and (or gnus-slave gnus-use-dribble-file) (gnus-dribble-read-file))
+         (when (or gnus-slave gnus-use-dribble-file)
+           (gnus-dribble-read-file))
+
+         ;; Allow using GroupLens predictions.
+         (when gnus-use-grouplens
+           (bbb-login)
+           (add-hook 'gnus-summary-mode-hook 'gnus-grouplens-mode))
 
          (gnus-summary-make-display-table)
          ;; Do the actual startup.
-         (gnus-setup-news nil level)
+         (gnus-setup-news nil level dont-connect)
          ;; Generate the group buffer.
          (gnus-group-list-groups level)
+         (gnus-group-first-unread-group)
          (gnus-configure-windows 'group)
          (gnus-group-set-mode-line))))))
 
@@ -4012,7 +4440,7 @@ prompt the user for the name of an NNTP server to use."
   (let ((history load-history)
        feature)
     (while history
-      (and (string-match "^gnus" (car (car history)))
+      (and (string-match "^\\(gnus\\|nn\\)" (caar history))
           (setq feature (cdr (assq 'provide (car history))))
           (unload-feature feature 'force))
       (setq history (cdr history)))))
@@ -4031,7 +4459,7 @@ prompt the user for the name of an NNTP server to use."
            (setq gnus-format-specs (delq entry gnus-format-specs))
          (when (and (listp (caddr entry))
                     (not (eq 'byte-code (caaddr entry))))
-           (fset 'gnus-tmp-func 
+           (fset 'gnus-tmp-func
                  `(lambda () ,(caddr entry)))
            (byte-compile 'gnus-tmp-func)
            (setcar (cddr entry) (gnus-byte-code 'gnus-tmp-func)))))
@@ -4048,7 +4476,7 @@ prompt the user for the name of an NNTP server to use."
       (indent-rigidly start end arg)
       (goto-char (point-min))
       (while (search-forward "\t" nil t)
-       (replace-match "        " t t)))))
+       (replace-match "        " t t)))))
 
 (defun gnus-group-startup-message (&optional x y)
   "Insert startup message in current buffer."
@@ -4056,28 +4484,28 @@ prompt the user for the name of an NNTP server to use."
   (erase-buffer)
   (insert
    (format "              %s
-          _    ___ _             _      
-          _ ___ __ ___  __    _ ___     
-          __   _     ___    __  ___     
-              _           ___     _     
-             _  _ __             _      
-             ___   __            _      
-                   __           _       
-                    _      _   _        
-                   _      _    _        
-                      _  _    _         
-                  __  ___               
-                 _   _ _     _          
-                _   _                   
-              _    _                    
-             _    _                     
-            _                         
-          __                             
-
-" 
-          ""))
+          _    ___ _             _
+          _ ___ __ ___  __    _ ___
+          __   _     ___    __  ___
+              _           ___     _
+             _  _ __             _
+             ___   __            _
+                   __           _
+                    _      _   _
+                   _      _    _
+                      _  _    _
+                  __  ___
+                 _   _ _     _
+                _   _
+              _    _
+             _    _
+            _
+          __
+
+"
+           ""))
   ;; And then hack it.
-  (gnus-indent-rigidly (point-min) (point-max) 
+  (gnus-indent-rigidly (point-min) (point-max)
                       (/ (max (- (window-width) (or x 46)) 0) 2))
   (goto-char (point-min))
   (forward-line 1)
@@ -4088,45 +4516,13 @@ prompt the user for the name of an NNTP server to use."
   ;; Fontify some.
   (goto-char (point-min))
   (and (search-forward "Praxis" nil t)
-       (put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
+       (gnus-put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
   (goto-char (point-min))
   (let* ((mode-string (gnus-group-set-mode-line)))
-    (setq mode-line-buffer-identification 
+    (setq mode-line-buffer-identification
          (list (concat gnus-version (substring (car mode-string) 4))))
     (set-buffer-modified-p t)))
 
-(defun gnus-group-startup-message-old (&optional x y)
-  "Insert startup message in current buffer."
-  ;; Insert the message.
-  (erase-buffer)
-  (insert
-   (format "
-     %s
-           A newsreader 
-      for GNU Emacs
-
-        Based on GNUS 
-             written by 
-     Masanobu UMEDA
-
-       A Praxis Release
-      larsi@ifi.uio.no
-" 
-          gnus-version))
-  ;; And then hack it.
-  ;; 18 is the longest line.
-  (indent-rigidly (point-min) (point-max) 
-                 (/ (max (- (window-width) (or x 28)) 0) 2))
-  (goto-char (point-min))
-  ;; +4 is fuzzy factor.
-  (insert-char ?\n (/ (max (- (window-height) (or y 12)) 0) 2))
-
-  ;; Fontify some.
-  (goto-char (point-min))
-  (search-forward "Praxis")
-  (put-text-property (match-beginning 0) (match-end 0) 'face 'bold)
-  (goto-char (point-min)))
-
 (defun gnus-group-setup-buffer ()
   (or (get-buffer gnus-group-buffer)
       (progn
@@ -4139,7 +4535,7 @@ prompt the user for the name of an NNTP server to use."
   "List newsgroups with level LEVEL or lower that have unread articles.
 Default is all subscribed groups.
 If argument UNREAD is non-nil, groups with no unread articles are also
-listed." 
+listed."
   (interactive (list (if current-prefix-arg
                         (prefix-numeric-value current-prefix-arg)
                       (or
@@ -4153,32 +4549,37 @@ listed."
   (gnus-group-setup-buffer)            ;May call from out of group buffer
   (gnus-update-format-specifications)
   (let ((case-fold-search nil)
+       (props (text-properties-at (gnus-point-at-bol)))
        (group (gnus-group-group-name)))
+    (set-buffer gnus-group-buffer)
     (funcall gnus-group-prepare-function level unread lowest)
     (if (zerop (buffer-size))
        (gnus-message 5 gnus-no-groups-message)
-      (goto-char (point-min))
-      (if (not group)
-         ;; Go to the first group with unread articles.
-         (gnus-group-search-forward nil nil nil t)
-       ;; Find the right group to put point on.  If the current group
-       ;; has disapeared in the new listing, try to find the next
-       ;; one.  If no next one can be found, just leave point at the
-       ;; first newsgroup in the buffer.
-       (if (not (gnus-goto-char
-                 (text-property-any
-                  (point-min) (point-max) 
-                  'gnus-group (gnus-intern-safe group gnus-active-hashtb))))
-           (let ((newsrc (nthcdr 3 (gnus-gethash group gnus-newsrc-hashtb))))
-             (while (and newsrc
-                         (not (gnus-goto-char 
-                               (text-property-any 
-                                (point-min) (point-max) 'gnus-group 
-                                (gnus-intern-safe 
-                                 (car (car newsrc)) gnus-active-hashtb)))))
-               (setq newsrc (cdr newsrc)))
-             (or newsrc (progn (goto-char (point-max))
-                               (forward-line -1))))))
+      (goto-char (point-max))
+      (when (or (not gnus-group-goto-next-group-function)
+               (not (funcall gnus-group-goto-next-group-function 
+                             group props)))
+       (if (not group)
+           ;; Go to the first group with unread articles.
+           (gnus-group-search-forward t)
+         ;; Find the right group to put point on.  If the current group
+         ;; has disappeared in the new listing, try to find the next
+         ;; one.        If no next one can be found, just leave point at the
+         ;; first newsgroup in the buffer.
+         (if (not (gnus-goto-char
+                   (text-property-any
+                    (point-min) (point-max)
+                    'gnus-group (gnus-intern-safe group gnus-active-hashtb))))
+             (let ((newsrc (cdddr (gnus-gethash group gnus-newsrc-hashtb))))
+               (while (and newsrc
+                           (not (gnus-goto-char
+                                 (text-property-any
+                                  (point-min) (point-max) 'gnus-group
+                                  (gnus-intern-safe
+                                   (caar newsrc) gnus-active-hashtb)))))
+                 (setq newsrc (cdr newsrc)))
+               (or newsrc (progn (goto-char (point-max))
+                                 (forward-line -1)))))))
       ;; Adjust cursor point.
       (gnus-group-position-point))))
 
@@ -4188,13 +4589,12 @@ If ALL (the prefix), also list groups that have no unread articles."
   (interactive "nList groups on level: \nP")
   (gnus-group-list-groups level all level))
 
-(defun gnus-group-prepare-flat (level &optional all lowest regexp) 
+(defun gnus-group-prepare-flat (level &optional all lowest regexp)
   "List all newsgroups with unread articles of level LEVEL or lower.
 If ALL is non-nil, list groups that have no unread articles.
 If LOWEST is non-nil, list all newsgroups of level LOWEST or higher.
 If REGEXP, only list groups matching REGEXP."
   (set-buffer gnus-group-buffer)
-  (setq gnus-topic-indentation "")
   (let ((buffer-read-only nil)
        (newsrc (cdr gnus-newsrc-alist))
        (lowest (or lowest 1))
@@ -4211,12 +4611,14 @@ If REGEXP, only list groups matching REGEXP."
          (and unread                   ; This group might be bogus
               (or (not regexp)
                   (string-match regexp group))
-              (<= (setq clevel (gnus-info-level info)) level) 
+              (<= (setq clevel (gnus-info-level info)) level)
               (>= clevel lowest)
               (or all                  ; We list all groups?
-                  (eq unread t)        ; We list unactivated groups
-                  (> unread 0)         ; We list groups with unread articles
-                  (cdr (assq 'tick (gnus-info-marks info)))
+                  (if (eq unread t)    ; Unactivated?
+                      gnus-group-list-inactive-groups ; We list unactivated 
+                    (> unread 0))      ; We list groups with unread articles
+                  (and gnus-list-groups-with-ticked-articles
+                       (cdr (assq 'tick (gnus-info-marks info))))
                                        ; And groups with tickeds
                   ;; Check for permanent visibility.
                   (and gnus-permanently-visible-groups
@@ -4224,19 +4626,19 @@ If REGEXP, only list groups matching REGEXP."
                                      group))
                   (memq 'visible params)
                   (cdr (assq 'visible params)))
-              (gnus-group-insert-group-line 
-               group (gnus-info-level info) 
+              (gnus-group-insert-group-line
+               group (gnus-info-level info)
                (gnus-info-marks info) unread (gnus-info-method info)))))
-      
+
     ;; List dead groups.
     (and (>= level gnus-level-zombie) (<= lowest gnus-level-zombie)
-        (gnus-group-prepare-flat-list-dead 
-         (setq gnus-zombie-list (sort gnus-zombie-list 'string<)) 
+        (gnus-group-prepare-flat-list-dead
+         (setq gnus-zombie-list (sort gnus-zombie-list 'string<))
          gnus-level-zombie ?Z
          regexp))
     (and (>= level gnus-level-killed) (<= lowest gnus-level-killed)
-        (gnus-group-prepare-flat-list-dead 
-         (setq gnus-killed-list (sort gnus-killed-list 'string<)) 
+        (gnus-group-prepare-flat-list-dead
+         (setq gnus-killed-list (sort gnus-killed-list 'string<))
          gnus-level-killed ?K regexp))
 
     (gnus-group-set-mode-line)
@@ -4244,17 +4646,17 @@ If REGEXP, only list groups matching REGEXP."
     (run-hooks 'gnus-group-prepare-hook)))
 
 (defun gnus-group-prepare-flat-list-dead (groups level mark regexp)
-  ;; List zombies and killed lists somehwat faster, which was
+  ;; List zombies and killed lists somewhat faster, which was
   ;; suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.  It does
   ;; this by ignoring the group format specification altogether.
-  (let (group beg)
+  (let (group)
     (if regexp
        ;; This loop is used when listing groups that match some
-       ;; regexp. 
+       ;; regexp.
        (while groups
          (setq group (pop groups))
          (when (string-match regexp group)
-           (add-text-properties 
+           (gnus-add-text-properties
             (point) (prog1 (1+ (point))
                       (insert " " mark "     *: " group "\n"))
             (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
@@ -4262,9 +4664,9 @@ If REGEXP, only list groups matching REGEXP."
                   'gnus-level level))))
       ;; This loop is used when listing all groups.
       (while groups
-       (add-text-properties 
+       (gnus-add-text-properties
         (point) (prog1 (1+ (point))
-                  (insert " " mark "     *: " 
+                  (insert " " mark "     *: "
                           (setq group (pop groups)) "\n"))
         (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
               'gnus-unread t
@@ -4287,25 +4689,77 @@ If REGEXP, only list groups matching REGEXP."
 
 (defsubst gnus-server-get-method (group method)
   ;; Input either a server name, and extended server name, or a
-  ;; select method, and return a select method. 
+  ;; select method, and return a select method.
   (cond ((stringp method)
         (gnus-server-to-method method))
+       ((equal method gnus-select-method)
+        gnus-select-method)
        ((and (stringp (car method)) group)
         (gnus-server-extend-method group method))
+       ((and method (not group)
+             (equal (cadr method) ""))
+        method)
        (t
         (gnus-server-add-address method))))
 
 (defun gnus-server-to-method (server)
   "Map virtual server names to select methods."
-  (or (and (equal server "native") gnus-select-method)
-      (cdr (assoc server gnus-server-alist))))
-
-(defun gnus-group-prefixed-name (group method)
-  "Return the whole name from GROUP and METHOD."
-  (and (stringp method) (setq method (gnus-server-to-method method)))
+  (or 
+   ;; Is this a method, perhaps?
+   (and server (listp server) server)
+   ;; Perhaps this is the native server?
+   (and (equal server "native") gnus-select-method)
+   ;; It should be in the server alist.
+   (cdr (assoc server gnus-server-alist))
+   ;; If not, we look through all the opened server
+   ;; to see whether we can find it there.
+   (let ((opened gnus-opened-servers))
+     (while (and opened
+                (not (equal server (format "%s:%s" (caaar opened)
+                                           (cadaar opened)))))
+       (pop opened))
+     (caar opened))))
+
+(defmacro gnus-method-equal (ss1 ss2)
+  "Say whether two servers are equal."
+  `(let ((s1 ,ss1)
+        (s2 ,ss2))
+     (or (equal s1 s2)
+        (and (= (length s1) (length s2))
+             (progn
+               (while (and s1 (member (car s1) s2))
+                 (setq s1 (cdr s1)))
+               (null s1))))))
+
+(defun gnus-server-equal (m1 m2)
+  "Say whether two methods are equal."
+  (let ((m1 (cond ((null m1) gnus-select-method)
+                 ((stringp m1) (gnus-server-to-method m1))
+                 (t m1)))
+       (m2 (cond ((null m2) gnus-select-method)
+                 ((stringp m2) (gnus-server-to-method m2))
+                 (t m2))))
+    (gnus-method-equal m1 m2)))
+
+(defun gnus-servers-using-backend (backend)
+  "Return a list of known servers using BACKEND."
+  (let ((opened gnus-opened-servers)
+       out)
+    (while opened
+      (when (eq backend (caaar opened))
+       (push (caar opened) out))
+      (pop opened))
+    out))
+
+(defun gnus-group-prefixed-name (group method)
+  "Return the whole name from GROUP and METHOD."
+  (and (stringp method) (setq method (gnus-server-to-method method)))
   (concat (format "%s" (car method))
-         (if (and 
-              (assoc (format "%s" (car method)) (gnus-methods-using 'address))
+         (if (and
+              (or (assoc (format "%s" (car method)) 
+                         (gnus-methods-using 'address))
+                  (gnus-server-equal method gnus-message-archive-method))
+              (nth 1 method)
               (not (string= (nth 1 method) "")))
              (concat "+" (nth 1 method)))
          ":" group))
@@ -4316,22 +4770,36 @@ If REGEXP, only list groups matching REGEXP."
       (substring group 0 (match-end 0))
     ""))
 
-(defun gnus-group-method-name (group)
-  "Return the method used for selecting GROUP."
+(defun gnus-group-method (group)
+  "Return the server or method used for selecting GROUP."
   (let ((prefix (gnus-group-real-prefix group)))
     (if (equal prefix "")
        gnus-select-method
-      (if (string-match "^[^\\+]+\\+" prefix)
-         (list (intern (substring prefix 0 (1- (match-end 0))))
-               (substring prefix (match-end 0) (1- (length prefix))))
-       (list (intern (substring prefix 0 (1- (length prefix)))) "")))))
+      (let ((servers gnus-opened-servers)
+           (server "")
+           backend possible found)
+       (if (string-match "^[^\\+]+\\+" prefix)
+           (setq backend (intern (substring prefix 0 (1- (match-end 0))))
+                 server (substring prefix (match-end 0) (1- (length prefix))))
+         (setq backend (intern (substring prefix 0 (1- (length prefix))))))
+       (while servers
+         (when (eq (caaar servers) backend)
+           (setq possible (caar servers))
+           (when (equal (cadaar servers) server)
+             (setq found (caar servers))))
+         (pop servers))
+       (or (car (rassoc found gnus-server-alist))
+           found
+           (car (rassoc possible gnus-server-alist))
+           possible
+           (list backend server))))))
 
 (defsubst gnus-secondary-method-p (method)
   "Return whether METHOD is a secondary select method."
   (let ((methods gnus-secondary-select-methods)
        (gmethod (gnus-server-get-method nil method)))
     (while (and methods
-               (not (equal (gnus-server-get-method nil (car methods)) 
+               (not (equal (gnus-server-get-method nil (car methods))
                            gmethod)))
       (setq methods (cdr methods)))
     methods))
@@ -4368,14 +4836,29 @@ If SYMBOL, return the value of that symbol in the group parameters."
     (if (not info)
        () ; This is a dead group.  We just ignore it.
       ;; Cons the new param to the old one and update.
-      (gnus-group-set-info (cons param (gnus-info-params info)) 
+      (gnus-group-set-info (cons param (gnus-info-params info))
                           group 'params))))
 
+(defun gnus-group-set-parameter (group name value)
+  "Set parameter NAME to VALUE in GROUP."
+  (let ((info (gnus-get-info group)))
+    (if (not info)
+       () ; This is a dead group.  We just ignore it.
+      (let ((old-params (gnus-info-params info))
+           (new-params (list (cons name value))))
+       (while old-params
+         (if (or (not (listp (car old-params)))
+                 (not (eq (caar old-params) name)))
+             (setq new-params (append new-params (list (car old-params)))))
+         (setq old-params (cdr old-params)))
+       (gnus-group-set-info new-params group 'params)))))
+
 (defun gnus-group-add-score (group &optional score)
-  "Add SCORE to the GROUP score.  
+  "Add SCORE to the GROUP score.
 If SCORE is nil, add 1 to the score of GROUP."
   (let ((info (gnus-get-info group)))
-    (gnus-info-set-score info (+ (gnus-info-score info) (or score 1)))))
+    (when info
+      (gnus-info-set-score info (+ (gnus-info-score info) (or score 1))))))
 
 (defun gnus-summary-bubble-group ()
   "Increase the score of the current group.
@@ -4388,12 +4871,13 @@ increase the score of each group you read."
                 (or method-only-group (gnus-info-group info))
                 gnus-newsrc-hashtb))
         (part-info info)
-        (info (if method-only-group (nth 2 entry) info)))
+        (info (if method-only-group (nth 2 entry) info))
+        method)
     (when method-only-group
       (unless entry
        (error "Trying to change non-existent group %s" method-only-group))
-      ;; We have recevied parts of the actual group info - either the
-      ;; select method or the group parameters.  We first check
+      ;; We have received parts of the actual group info - either the
+      ;; select method or the group parameters.         We first check
       ;; whether we have to extend the info, and if so, do that.
       (let ((len (length info))
            (total (if (eq part 'method) 5 6)))
@@ -4406,17 +4890,24 @@ increase the score of each group you read."
       ;; This is a new group, so we just create it.
       (save-excursion
        (set-buffer gnus-group-buffer)
-       (if (gnus-info-method info)
-           ;; It's a foreign group...
-           (gnus-group-make-group 
-            (gnus-group-real-name (gnus-info-group info))
-            (prin1-to-string (car (gnus-info-method info)))
-            (nth 1 (gnus-info-method info)))
-         ;; It's a native group.
-         (gnus-group-make-group (gnus-info-group info)))
+       (setq method (gnus-info-method info))
+       (when (gnus-server-equal method "native")
+         (setq method nil))
+       (save-excursion
+         (set-buffer gnus-group-buffer)
+         (if method
+             ;; It's a foreign group...
+             (gnus-group-make-group
+              (gnus-group-real-name (gnus-info-group info))
+              (if (stringp method) method
+                (prin1-to-string (car method)))
+              (and (consp method)
+                   (nth 1 (gnus-info-method info))))
+           ;; It's a native group.
+           (gnus-group-make-group (gnus-info-group info))))
        (gnus-message 6 "Note: New group created")
-       (setq entry 
-             (gnus-gethash (gnus-group-prefixed-name 
+       (setq entry
+             (gnus-gethash (gnus-group-prefixed-name
                             (gnus-group-real-name (gnus-info-group info))
                             (or (gnus-info-method info) gnus-select-method))
                            gnus-newsrc-hashtb))))
@@ -4425,11 +4916,9 @@ increase the score of each group you read."
     (if entry
        (progn
          (setcar (nthcdr 2 entry) info)
-         (when (and (not (eq (car entry) t)) 
+         (when (and (not (eq (car entry) t))
                     (gnus-active (gnus-info-group info)))
-           (let ((marked (gnus-info-marks info)))
-             (setcar entry (length (gnus-list-of-unread-articles 
-                                    (car info)))))))
+           (setcar entry (length (gnus-list-of-unread-articles (car info))))))
       (error "No such group: %s" (gnus-info-group info)))))
 
 (defun gnus-group-set-method-info (group select-method)
@@ -4442,55 +4931,55 @@ increase the score of each group you read."
   "Update the current line in the group buffer."
   (let* ((buffer-read-only nil)
         (group (gnus-group-group-name))
-        (entry (and group (gnus-gethash group gnus-newsrc-hashtb))))
-    (and entry 
-        (not (gnus-ephemeral-group-p group))
-        (gnus-dribble-enter 
-         (concat "(gnus-group-set-info '" 
-                 (prin1-to-string (nth 2 entry)) ")")))
-    (gnus-delete-line)
-    (gnus-group-insert-group-line-info group)
-    (forward-line -1)
-    (gnus-group-position-point)))
+        (entry (and group (gnus-gethash group gnus-newsrc-hashtb)))
+        gnus-group-indentation)
+    (when group
+      (and entry
+          (not (gnus-ephemeral-group-p group))
+          (gnus-dribble-enter
+           (concat "(gnus-group-set-info '"
+                   (prin1-to-string (nth 2 entry)) ")")))
+      (setq gnus-group-indentation (gnus-group-group-indentation))
+      (gnus-delete-line)
+      (gnus-group-insert-group-line-info group)
+      (forward-line -1)
+      (gnus-group-position-point))))
 
 (defun gnus-group-insert-group-line-info (group)
   "Insert GROUP on the current line."
-  (let ((entry (gnus-gethash group gnus-newsrc-hashtb)) 
+  (let ((entry (gnus-gethash group gnus-newsrc-hashtb))
        active info)
     (if entry
        (progn
          ;; (Un)subscribed group.
          (setq info (nth 2 entry))
-         (gnus-group-insert-group-line 
+         (gnus-group-insert-group-line
           group (gnus-info-level info) (gnus-info-marks info)
           (or (car entry) t) (gnus-info-method info)))
       ;; This group is dead.
-      (gnus-group-insert-group-line 
-       group 
+      (gnus-group-insert-group-line
+       group
        (if (member group gnus-zombie-list) gnus-level-zombie gnus-level-killed)
-       nil 
+       nil
        (if (setq active (gnus-active group))
-          (- (1+ (cdr active)) (car active)) 0) 
+          (- (1+ (cdr active)) (car active)) 0)
        nil))))
 
-;; Dummy function redefined when running under XEmacs.
-(defalias 'gnus-group-remove-excess-properties 'ignore)
-
-(defun gnus-group-insert-group-line 
-  (gnus-tmp-group gnus-tmp-level gnus-tmp-marked number
-                 gnus-tmp-method)
+(defun gnus-group-insert-group-line (gnus-tmp-group gnus-tmp-level 
+                                                   gnus-tmp-marked number
+                                                   gnus-tmp-method)
   "Insert a group line in the group buffer."
   (let* ((gnus-tmp-active (gnus-active gnus-tmp-group))
-        (gnus-tmp-number-total 
-         (if gnus-tmp-active 
+        (gnus-tmp-number-total
+         (if gnus-tmp-active
              (1+ (- (cdr gnus-tmp-active) (car gnus-tmp-active)))
            0))
-        (gnus-tmp-number-of-unread 
+        (gnus-tmp-number-of-unread
          (if (numberp number) (int-to-string (max 0 number))
            "*"))
         (gnus-tmp-number-of-read
          (if (numberp number)
-             (max 0 (- gnus-tmp-number-total number))
+             (int-to-string (max 0 (- gnus-tmp-number-total number)))
            "*"))
         (gnus-tmp-subscribed
          (cond ((<= gnus-tmp-level gnus-level-subscribed) ? )
@@ -4498,38 +4987,38 @@ increase the score of each group you read."
                ((= gnus-tmp-level gnus-level-zombie) ?Z)
                (t ?K)))
         (gnus-tmp-qualified-group (gnus-group-real-name gnus-tmp-group))
-        (gnus-tmp-newsgroup-description 
+        (gnus-tmp-newsgroup-description
          (if gnus-description-hashtb
              (or (gnus-gethash gnus-tmp-group gnus-description-hashtb) "")
            ""))
         (gnus-tmp-moderated
          (if (member gnus-tmp-group gnus-moderated-list) ?m ? ))
-        (gnus-tmp-moderated-string 
+        (gnus-tmp-moderated-string
          (if (eq gnus-tmp-moderated ?m) "(m)" ""))
         (gnus-tmp-method
          (gnus-server-get-method gnus-tmp-group gnus-tmp-method))
-        (gnus-tmp-news-server (or (car (cdr gnus-tmp-method)) ""))
+        (gnus-tmp-news-server (or (cadr gnus-tmp-method) ""))
         (gnus-tmp-news-method (or (car gnus-tmp-method) ""))
-        (gnus-tmp-news-method-string 
+        (gnus-tmp-news-method-string
          (if gnus-tmp-method
              (format "(%s:%s)" (car gnus-tmp-method)
-                     (car (cdr gnus-tmp-method))) ""))
-        (gnus-tmp-marked-mark 
-         (if (and (numberp number) 
+                     (cadr gnus-tmp-method)) ""))
+        (gnus-tmp-marked-mark
+         (if (and (numberp number)
                   (zerop number)
                   (cdr (assq 'tick gnus-tmp-marked)))
              ?* ? ))
-        (gnus-tmp-number
-         (cond ((eq number t) "*" )
-               ((numberp number) (int-to-string number))
-               (t number)))
         (gnus-tmp-process-marked
          (if (member gnus-tmp-group gnus-group-marked)
              gnus-process-mark ? ))
+        (gnus-tmp-grouplens
+         (or (and gnus-use-grouplens
+                  (bbb-grouplens-group-p gnus-tmp-group))
+             ""))
         (buffer-read-only nil)
-        header)                        ; passed as parameter to user-funcs.
+        header gnus-tmp-header)        ; passed as parameter to user-funcs.
     (beginning-of-line)
-    (add-text-properties
+    (gnus-add-text-properties
      (point)
      (prog1 (1+ (point))
        ;; Insert the text.
@@ -4539,14 +5028,19 @@ increase the score of each group you read."
                        (string-to-int gnus-tmp-number-of-unread)
                      t)
        gnus-marked ,gnus-tmp-marked-mark
+       gnus-indentation ,gnus-group-indentation
        gnus-level ,gnus-tmp-level))
+    (when (inline (gnus-visual-p 'group-highlight 'highlight))
+      (forward-line -1)
+      (run-hooks 'gnus-group-update-hook)
+      (forward-line))
     ;; Allow XEmacs to remove front-sticky text properties.
     (gnus-group-remove-excess-properties)))
 
 (defun gnus-group-update-group (group &optional visible-only)
   "Update all lines where GROUP appear.
 If VISIBLE-ONLY is non-nil, the group won't be displayed if it isn't
-already." 
+already."
   (save-excursion
     (set-buffer gnus-group-buffer)
     ;; The buffer may be narrowed.
@@ -4554,61 +5048,85 @@ already."
       (widen)
       (let ((ident (gnus-intern-safe group gnus-active-hashtb))
            (loc (point-min))
-           found buffer-read-only visible)
+           found buffer-read-only)
        ;; Enter the current status into the dribble buffer.
        (let ((entry (gnus-gethash group gnus-newsrc-hashtb)))
          (if (and entry (not (gnus-ephemeral-group-p group)))
-             (gnus-dribble-enter 
+             (gnus-dribble-enter
               (concat "(gnus-group-set-info '" (prin1-to-string (nth 2 entry))
                       ")"))))
        ;; Find all group instances.  If topics are in use, each group
        ;; may be listed in more than once.
-       (while (setq loc (text-property-any 
+       (while (setq loc (text-property-any
                          loc (point-max) 'gnus-group ident))
          (setq found t)
          (goto-char loc)
-         (gnus-delete-line)
-         (gnus-group-insert-group-line-info group)
+         (let ((gnus-group-indentation (gnus-group-group-indentation)))
+           (gnus-delete-line)
+           (gnus-group-insert-group-line-info group)
+           (save-excursion
+             (forward-line -1)
+             (run-hooks 'gnus-group-update-group-hook)))
          (setq loc (1+ loc)))
-       (if (or found visible-only)
-           ()
+       (unless (or found visible-only)
          ;; No such line in the buffer, find out where it's supposed to
          ;; go, and insert it there (or at the end of the buffer).
-         ;; Fix by Per Abrahamsen <amanda@iesd.auc.dk>.
-         (let ((entry (cdr (cdr (gnus-gethash group gnus-newsrc-hashtb)))))
-           (while (and entry (car entry)
-                       (not
-                        (gnus-goto-char
-                         (text-property-any
-                          (point-min) (point-max) 
-                          'gnus-group (gnus-intern-safe 
-                                       (car (car entry)) 
-                                       gnus-active-hashtb)))))
-             (setq entry (cdr entry)))
-           (or entry (goto-char (point-max))))
+         (if gnus-goto-missing-group-function
+             (funcall gnus-goto-missing-group-function group)
+           (let ((entry (cddr (gnus-gethash group gnus-newsrc-hashtb))))
+             (while (and entry (car entry)
+                         (not
+                          (gnus-goto-char
+                           (text-property-any
+                            (point-min) (point-max)
+                            'gnus-group (gnus-intern-safe
+                                         (caar entry) gnus-active-hashtb)))))
+               (setq entry (cdr entry)))
+             (or entry (goto-char (point-max)))))
          ;; Finally insert the line.
-         (gnus-group-insert-group-line-info group))
+         (let ((gnus-group-indentation (gnus-group-group-indentation)))
+           (gnus-group-insert-group-line-info group)
+           (save-excursion
+             (forward-line -1)
+             (run-hooks 'gnus-group-update-group-hook))))
        (gnus-group-set-mode-line)))))
 
 (defun gnus-group-set-mode-line ()
+  "Update the mode line in the group buffer."
   (when (memq 'group gnus-updated-mode-lines)
-    (let* ((gformat (or gnus-group-mode-line-format-spec
-                       (setq gnus-group-mode-line-format-spec
-                             (gnus-parse-format 
-                              gnus-group-mode-line-format 
-                              gnus-group-mode-line-format-alist))))
-          (gnus-tmp-news-server (car (cdr gnus-select-method)))
-          (gnus-tmp-news-method (car gnus-select-method))
-          (max-len 60)
-          header                       ;Dummy binding for user-defined formats
-          ;; Get the resulting string.
-          (mode-string (eval gformat)))
-      ;; If the line is too long, we chop it off.
-      (when (> (length mode-string) max-len) 
-       (setq mode-string (substring mode-string 0 (- max-len 4))))
-      (prog1
-         (setq mode-line-buffer-identification (list mode-string))
-       (set-buffer-modified-p t)))))
+    ;; Yes, we want to keep this mode line updated.
+    (save-excursion
+      (set-buffer gnus-group-buffer)
+      (let* ((gformat (or gnus-group-mode-line-format-spec
+                         (setq gnus-group-mode-line-format-spec
+                               (gnus-parse-format
+                                gnus-group-mode-line-format
+                                gnus-group-mode-line-format-alist))))
+            (gnus-tmp-news-server (cadr gnus-select-method))
+            (gnus-tmp-news-method (car gnus-select-method))
+            (gnus-tmp-colon (if (equal gnus-tmp-news-server "") "" ":"))
+            (max-len 60)
+            gnus-tmp-header            ;Dummy binding for user-defined formats
+            ;; Get the resulting string.
+            (modified 
+             (and gnus-dribble-buffer
+                  (buffer-name gnus-dribble-buffer)
+                  (buffer-modified-p gnus-dribble-buffer)
+                  (save-excursion
+                    (set-buffer gnus-dribble-buffer)
+                    (not (zerop (buffer-size))))))
+            (mode-string (eval gformat)))
+       ;; Say whether the dribble buffer has been modified.
+       (setq mode-line-modified
+             (if modified "---*- " "----- "))
+       ;; If the line is too long, we chop it off.
+       (when (> (length mode-string) max-len)
+         (setq mode-string (substring mode-string 0 (- max-len 4))))
+       (prog1
+           (setq mode-line-buffer-identification 
+                 (gnus-mode-line-buffer-identification
+                  (list mode-string)))
+         (set-buffer-modified-p modified))))))
 
 (defun gnus-group-group-name ()
   "Get the name of the newsgroup on the current line."
@@ -4619,6 +5137,13 @@ already."
   "Get the level of the newsgroup on the current line."
   (get-text-property (gnus-point-at-bol) 'gnus-level))
 
+(defun gnus-group-group-indentation ()
+  "Get the indentation of the newsgroup on the current line."
+  (or (get-text-property (gnus-point-at-bol) 'gnus-indentation)
+      (and gnus-group-indentation-function
+          (funcall gnus-group-indentation-function))
+      ""))
+
 (defun gnus-group-group-unread ()
   "Get the number of unread articles of the newsgroup on the current line."
   (get-text-property (gnus-point-at-bol) 'gnus-unread))
@@ -4637,13 +5162,13 @@ If FIRST-TOO, the current line is also eligible as a target."
     (if (and backward (progn (beginning-of-line)) (bobp))
        nil
       (or first-too (forward-line way))
-      (while (and 
+      (while (and
              (not (eobp))
-             (not (setq 
-                   found 
+             (not (setq
+                   found
                    (and (or all
                             (and
-                             (let ((unread 
+                             (let ((unread
                                     (get-text-property (point) 'gnus-unread)))
                                (and (numberp unread) (> unread 0)))
                              (setq lev (get-text-property (point)
@@ -4660,7 +5185,7 @@ If FIRST-TOO, the current line is also eligible as a target."
                                             (setq pos (point))
                                             nil))))))))
              (zerop (forward-line way)))))
-    (if found 
+    (if found
        (progn (gnus-group-position-point) t)
       (goto-char (or pos beg))
       (and pos t))))
@@ -4674,31 +5199,40 @@ If FIRST-TOO, the current line is also eligible as a target."
   (interactive "p")
   (let ((buffer-read-only nil)
        group)
-    (while 
-       (and (> n 0) 
-            (setq group (gnus-group-group-name))
-            (progn
-              (beginning-of-line)
-              (forward-char 
-               (or (cdr (assq 'process gnus-group-mark-positions)) 2))
-              (delete-char 1)
-              (if unmark
-                  (progn
-                    (insert " ")
-                    (setq gnus-group-marked (delete group gnus-group-marked)))
-                (insert "#")
-                (setq gnus-group-marked
-                      (cons group (delete group gnus-group-marked))))
-              t)
-            (or no-advance (zerop (gnus-group-next-group 1))))
-      (setq n (1- n)))
+    (while (and (> n 0)
+               (not (eobp)))
+      (when (setq group (gnus-group-group-name))
+       ;; Update the mark.
+       (beginning-of-line)
+       (forward-char
+        (or (cdr (assq 'process gnus-group-mark-positions)) 2))
+       (delete-char 1)
+       (if unmark
+           (progn
+             (insert " ")
+             (setq gnus-group-marked (delete group gnus-group-marked)))
+         (insert "#")
+         (setq gnus-group-marked
+               (cons group (delete group gnus-group-marked)))))
+      (or no-advance (gnus-group-next-group 1))
+      (decf n))
     (gnus-summary-position-point)
     n))
 
 (defun gnus-group-unmark-group (n)
   "Remove the mark from the current group."
   (interactive "p")
-  (gnus-group-mark-group n 'unmark))
+  (gnus-group-mark-group n 'unmark)
+  (gnus-group-position-point))
+
+(defun gnus-group-unmark-all-groups ()
+  "Unmark all groups."
+  (interactive)
+  (let ((groups gnus-group-marked))
+    (save-excursion
+      (while groups
+       (gnus-group-remove-mark (pop groups)))))
+  (gnus-group-position-point))
 
 (defun gnus-group-mark-region (unmark beg end)
   "Mark all groups between point and mark.
@@ -4709,6 +5243,12 @@ If UNMARK, remove the mark instead."
       (goto-char beg)
       (- num (gnus-group-mark-group num unmark)))))
 
+(defun gnus-group-mark-buffer (&optional unmark)
+  "Mark all groups in the buffer.
+If UNMARK, remove the mark instead."
+  (interactive "P")
+  (gnus-group-mark-region unmark (point-min) (point-max)))
+
 (defun gnus-group-mark-regexp (regexp)
   "Mark all groups that match some regexp."
   (interactive "sMark (regexp): ")
@@ -4716,30 +5256,52 @@ If UNMARK, remove the mark instead."
        group)
     (while alist
       (when (string-match regexp (setq group (gnus-info-group (pop alist))))
-       (gnus-group-set-mark group)))))
+       (gnus-group-set-mark group))))
+  (gnus-group-position-point))
 
 (defun gnus-group-remove-mark (group)
+  "Remove the process mark from GROUP and move point there.
+Return nil if the group isn't displayed."
   (if (gnus-group-goto-group group)
       (save-excursion
-       (gnus-group-mark-group 1 'unmark t))
+       (gnus-group-mark-group 1 'unmark t)
+       t)
     (setq gnus-group-marked
-         (cons group (delete group gnus-group-marked)))))
-               
+         (delete group gnus-group-marked))
+    nil))
+
 (defun gnus-group-set-mark (group)
-  (if (gnus-group-goto-group group)
+  "Set the process mark on GROUP."
+  (if (gnus-group-goto-group group) 
       (save-excursion
        (gnus-group-mark-group 1 nil t))
-    (setq gnus-group-marked
-         (cons group (delete group gnus-group-marked)))))
-               
-;; Return a list of groups to work on.  Take into consideration N (the
-;; prefix) and the list of marked groups.
+    (setq gnus-group-marked (cons group (delete group gnus-group-marked)))))
+
+(defun gnus-group-universal-argument (arg &optional groups func)
+  "Perform any command on all groups accoring to the process/prefix convention."
+  (interactive "P")
+  (let ((groups (or groups (gnus-group-process-prefix arg)))
+       group func)
+    (if (eq (setq func (or func
+                          (key-binding
+                           (read-key-sequence
+                            (substitute-command-keys
+                             "\\<gnus-group-mode-map>\\[gnus-group-universal-argument]")))))
+           'undefined)
+       (gnus-error 1 "Undefined key")
+      (while groups
+       (gnus-group-remove-mark (setq group (pop groups)))
+       (command-execute func))))
+  (gnus-group-position-point))
+
 (defun gnus-group-process-prefix (n)
+  "Return a list of groups to work on.
+Take into consideration N (the prefix) and the list of marked groups."
   (cond
    (n
     (setq n (prefix-numeric-value n))
     ;; There is a prefix, so we return a list of the N next
-    ;; groups. 
+    ;; groups.
     (let ((way (if (< n 0) -1 1))
          (n (abs n))
          group groups)
@@ -4752,14 +5314,15 @@ If UNMARK, remove the mark instead."
       (nreverse groups)))
    ((and (boundp 'transient-mark-mode)
         transient-mark-mode
+        (boundp 'mark-active)
         mark-active)
     ;; Work on the region between point and mark.
     (let ((max (max (point) (mark)))
          groups)
       (save-excursion
        (goto-char (min (point) (mark)))
-       (while 
-           (and 
+       (while
+           (and
             (push (gnus-group-group-name) groups)
             (zerop (gnus-group-next-group 1))
             (< (point) max)))
@@ -4780,7 +5343,7 @@ If UNMARK, remove the mark instead."
 If the prefix argument ALL is non-nil, already read articles become
 readable.  IF ALL is a number, fetch this number of articles.  If the
 optional argument NO-ARTICLE is non-nil, no article will be
-auto-selected upon group entry.  If GROUP is non-nil, fetch that
+auto-selected upon group entry.         If GROUP is non-nil, fetch that
 group."
   (interactive "P")
   (let ((group (or group (gnus-group-group-name)))
@@ -4795,8 +5358,8 @@ group."
                (entry (car entry))
                ((setq active (gnus-active group))
                 (- (1+ (cdr active)) (car active)))))
-    (gnus-summary-read-group 
-     group (or all (and (numberp number) 
+    (gnus-summary-read-group
+     group (or all (and (numberp number)
                        (zerop (+ number (length (cdr (assq 'tick marked)))
                                  (length (cdr (assq 'dormant marked)))))))
      no-article)))
@@ -4810,7 +5373,7 @@ If ALL is a number, fetch this number of articles."
   (gnus-group-read-group all t))
 
 (defun gnus-group-quick-select-group (&optional all)
-  "Select the current group \"quickly\". 
+  "Select the current group \"quickly\".
 This means that no highlighting or scoring will be performed."
   (interactive "P")
   (let (gnus-visual
@@ -4832,23 +5395,19 @@ Returns whether the fetching was successful or not."
   (interactive "sGroup name: ")
   (or (get-buffer gnus-group-buffer)
       (gnus))
-  (gnus-group-select-group))
+  (gnus-group-read-group nil nil group))
 
 ;; Enter a group that is not in the group buffer.  Non-nil is returned
 ;; if selection was successful.
-(defun gnus-group-read-ephemeral-group 
+(defun gnus-group-read-ephemeral-group
   (group method &optional activate quit-config)
   (let ((group (if (gnus-group-foreign-p group) group
-                (gnus-group-prefixed-name group method)))
-       (cur (current-buffer)))
-    (gnus-sethash 
+                (gnus-group-prefixed-name group method))))
+    (gnus-sethash
      group
-     (list t nil (list group gnus-level-default-subscribed nil nil 
-                      (append method
-                              (list
-                               (list 'quit-config 
-                                     (if quit-config quit-config
-                                       (cons (current-buffer) 'summary)))))))
+     `(t nil (,group ,gnus-level-default-subscribed nil nil ,method
+                    ((quit-config . ,(if quit-config quit-config
+                                       (cons (current-buffer) 'summary))))))
      gnus-newsrc-hashtb)
     (set-buffer gnus-group-buffer)
     (or (gnus-check-server method)
@@ -4858,42 +5417,47 @@ Returns whether the fetching was successful or not."
     (condition-case ()
        (gnus-group-read-group t t group)
       (error nil)
-      (quit nil))
-    (not (equal (current-buffer) cur))))
-  
+      (quit nil))))
+
 (defun gnus-group-jump-to-group (group)
   "Jump to newsgroup GROUP."
-  (interactive 
-   (list (completing-read 
-         "Group: " gnus-active-hashtb nil 
-         (memq gnus-select-method gnus-have-read-active-file))))
+  (interactive
+   (list (completing-read
+         "Group: " gnus-active-hashtb nil
+         (gnus-read-active-file-p)
+         nil
+         'gnus-group-history)))
 
-  (if (equal group "")
-      (error "Empty group name"))
+  (when (equal group "")
+    (error "Empty group name"))
+
+  (when (string-match "[\000-\032]" group)
+    (error "Control characters in group: %s" group))
 
-  (let ((b (text-property-any 
-           (point-min) (point-max) 
+  (let ((b (text-property-any
+           (point-min) (point-max)
            'gnus-group (gnus-intern-safe group gnus-active-hashtb))))
-    (if b
-       ;; Either go to the line in the group buffer...
-       (goto-char b)
-      ;; ... or insert the line.
-      (or
-       (gnus-active group)
-       (gnus-activate-group group)
-       (error "%s error: %s" group (gnus-status-message group)))
-
-      (gnus-group-update-group group)
-      (goto-char (text-property-any 
-                 (point-min) (point-max)
-                 'gnus-group (gnus-intern-safe group gnus-active-hashtb)))))
-  ;; Adjust cursor point.
-  (gnus-group-position-point))
+    (unless (gnus-ephemeral-group-p group)
+      (if b
+         ;; Either go to the line in the group buffer...
+         (goto-char b)
+       ;; ... or insert the line.
+       (or
+        (gnus-active group)
+        (gnus-activate-group group)
+        (error "%s error: %s" group (gnus-status-message group)))
+
+       (gnus-group-update-group group)
+       (goto-char (text-property-any
+                   (point-min) (point-max)
+                   'gnus-group (gnus-intern-safe group gnus-active-hashtb)))))
+    ;; Adjust cursor point.
+    (gnus-group-position-point)))
 
 (defun gnus-group-goto-group (group)
   "Goto to newsgroup GROUP."
   (when group
-    (let ((b (text-property-any (point-min) (point-max) 
+    (let ((b (text-property-any (point-min) (point-max)
                                'gnus-group (gnus-intern-safe
                                             group gnus-active-hashtb))))
       (and b (goto-char b)))))
@@ -4919,7 +5483,7 @@ made."
   (let ((backward (< n 0))
        (n (abs n)))
     (while (and (> n 0)
-               (gnus-group-search-forward 
+               (gnus-group-search-forward
                 backward (or (not gnus-group-goto-unread) all) level))
       (setq n (1- n)))
     (if (/= 0 n) (gnus-message 7 "No more%s newsgroups%s" (if all "" " unread")
@@ -4936,7 +5500,7 @@ done."
 (defun gnus-group-prev-unread-group (n)
   "Go to previous N'th unread newsgroup.
 Returns the difference between N and the number of skips actually
-done."  
+done."
   (interactive "p")
   (gnus-group-next-unread-group (- n)))
 
@@ -4964,13 +5528,15 @@ If EXCLUDE-GROUP, do not go to that group."
   (goto-char (point-min))
   (let ((best 100000)
        unread best-point)
-    (while (setq unread (get-text-property (point) 'gnus-unread))
+    (while (not (eobp))
+      (setq unread (get-text-property (point) 'gnus-unread))
       (if (and (numberp unread) (> unread 0))
          (progn
-           (if (and (< (get-text-property (point) 'gnus-level) best)
+           (if (and (get-text-property (point) 'gnus-level)
+                    (< (get-text-property (point) 'gnus-level) best)
                     (or (not exclude-group)
                         (not (equal exclude-group (gnus-group-group-name)))))
-               (progn 
+               (progn
                  (setq best (get-text-property (point) 'gnus-level))
                  (setq best-point (point))))))
       (forward-line 1))
@@ -5004,53 +5570,65 @@ If EXCLUDE-GROUP, do not go to that group."
 The user will be prompted for a NAME, for a select METHOD, and an
 ADDRESS."
   (interactive
-   (cons 
+   (cons
     (read-string "Group name: ")
     (let ((method
-          (completing-read 
+          (completing-read
            "Method: " (append gnus-valid-select-methods gnus-server-alist)
-           nil t)))
-      (if (assoc method gnus-valid-select-methods)
-         (list method
-               (if (memq 'prompt-address
-                         (assoc method gnus-valid-select-methods))
-                   (read-string "Address: ")
-                 ""))
-       (list method nil)))))
-  
-  (save-excursion
-    (set-buffer gnus-group-buffer)
-    (let* ((meth (and method (if address (list (intern method) address) 
-                              method)))
-          (nname (if method (gnus-group-prefixed-name name meth) name))
-          info)
-      (and (gnus-gethash nname gnus-newsrc-hashtb)
-          (error "Group %s already exists" nname))
-      (gnus-group-change-level 
-       (setq info (list t nname gnus-level-default-subscribed nil nil meth))
-       gnus-level-default-subscribed gnus-level-killed 
-       (and (gnus-group-group-name)
-           (gnus-gethash (gnus-group-group-name)
-                         gnus-newsrc-hashtb))
-       t)
-      (gnus-set-active nname (cons 1 0))
-      (or (gnus-ephemeral-group-p name)
-         (gnus-dribble-enter 
-          (concat "(gnus-group-set-info '" (prin1-to-string (cdr info)) ")")))
-      (gnus-group-insert-group-line-info nname)
-
-      (if (assoc method gnus-valid-select-methods)
-         (require (intern method)))
-      (and (gnus-check-backend-function 'request-create-group nname)
-          (gnus-request-create-group nname))
-      t)))
+           nil t nil 'gnus-method-history)))
+      (cond ((assoc method gnus-valid-select-methods)
+            (list method
+                  (if (memq 'prompt-address
+                            (assoc method gnus-valid-select-methods))
+                      (read-string "Address: ")
+                    "")))
+           ((assoc method gnus-server-alist)
+            (list method))
+           (t
+            (list method ""))))))
+
+  (let* ((meth (and method (if address (list (intern method) address)
+                            method)))
+        (nname (if method (gnus-group-prefixed-name name meth) name))
+        backend info)
+    (when (gnus-gethash nname gnus-newsrc-hashtb)
+      (error "Group %s already exists" nname))
+    ;; Subscribe to the new group.
+    (gnus-group-change-level
+     (setq info (list t nname gnus-level-default-subscribed nil nil meth))
+     gnus-level-default-subscribed gnus-level-killed
+     (and (gnus-group-group-name)
+         (gnus-gethash (gnus-group-group-name)
+                       gnus-newsrc-hashtb))
+     t)
+    ;; Make it active.
+    (gnus-set-active nname (cons 1 0))
+    (or (gnus-ephemeral-group-p name)
+       (gnus-dribble-enter
+        (concat "(gnus-group-set-info '" (prin1-to-string (cdr info)) ")")))
+    ;; Insert the line.
+    (gnus-group-insert-group-line-info nname)
+    (forward-line -1)
+    (gnus-group-position-point)
+
+    ;; Load the backend and try to make the backend create
+    ;; the group as well.
+    (when (assoc (symbol-name (setq backend (car (gnus-server-get-method
+                                                 nil meth))))
+                gnus-valid-select-methods)
+      (require backend))
+    (gnus-check-server meth)
+    (and (gnus-check-backend-function 'request-create-group nname)
+        (gnus-request-create-group nname))
+    t))
 
 (defun gnus-group-delete-group (group &optional force)
-  "Delete the current group.
+  "Delete the current group.  Only meaningful with mail groups.
 If FORCE (the prefix) is non-nil, all the articles in the group will
 be deleted.  This is \"deleted\" as in \"removed forever from the face
-of the Earth\".  There is no undo."
-  (interactive 
+of the Earth\".         There is no undo.  The user will be prompted before
+doing the deletion."
+  (interactive
    (list (gnus-group-group-name)
         current-prefix-arg))
   (or group (error "No group to rename"))
@@ -5059,17 +5637,16 @@ of the Earth\".  There is no undo."
   (prog1
       (if (not (gnus-yes-or-no-p
                (format
-                "Do you really want to delete %s%s? " 
+                "Do you really want to delete %s%s? "
                 group (if force " and all its contents" ""))))
          () ; Whew!
        (gnus-message 6 "Deleting group %s..." group)
        (if (not (gnus-request-delete-group group force))
-           (progn
-             (gnus-message 3 "Couldn't delete group %s" group)
-             (ding))
+           (gnus-error 3 "Couldn't delete group %s" group)
          (gnus-message 6 "Deleting group %s...done" group)
          (gnus-group-goto-group group)
          (gnus-group-kill-group 1 t)
+         (gnus-sethash group nil gnus-active-hashtb)
          t))
     (gnus-group-position-point)))
 
@@ -5078,7 +5655,7 @@ of the Earth\".  There is no undo."
    (list
     (gnus-group-group-name)
     (progn
-      (or (gnus-check-backend-function 
+      (or (gnus-check-backend-function
           'request-rename-group (gnus-group-group-name))
          (error "This backend does not support renaming groups"))
       (read-string "New group name: "))))
@@ -5087,45 +5664,41 @@ of the Earth\".  There is no undo."
       (error "This backend does not support renaming groups"))
 
   (or group (error "No group to rename"))
-  (and (string-match "^[ \t]*$" new-name) 
+  (and (string-match "^[ \t]*$" new-name)
        (error "Not a valid group name"))
 
   ;; We find the proper prefixed name.
   (setq new-name
-       (gnus-group-prefixed-name 
+       (gnus-group-prefixed-name
         (gnus-group-real-name new-name)
         (gnus-info-method (gnus-get-info group))))
 
   (gnus-message 6 "Renaming group %s to %s..." group new-name)
   (prog1
       (if (not (gnus-request-rename-group group new-name))
-         (progn
-           (gnus-message 3 "Couldn't rename group %s to %s" group new-name)
-           (ding))
+         (gnus-error 3 "Couldn't rename group %s to %s" group new-name)
        ;; We rename the group internally by killing it...
        (gnus-group-goto-group group)
        (gnus-group-kill-group)
        ;; ... changing its name ...
-       (setcar (cdr (car gnus-list-of-killed-groups))
-               new-name)
+       (setcar (cdar gnus-list-of-killed-groups) new-name)
        ;; ... and then yanking it.  Magic!
-       (gnus-group-yank-group) 
+       (gnus-group-yank-group)
        (gnus-set-active new-name (gnus-active group))
        (gnus-message 6 "Renaming group %s to %s...done" group new-name)
        new-name)
     (gnus-group-position-point)))
 
-
 (defun gnus-group-edit-group (group &optional part)
   "Edit the group on the current line."
   (interactive (list (gnus-group-group-name)))
-  (let ((done-func '(lambda () 
-                     "Exit editing mode and update the information."
-                     (interactive)
-                     (gnus-group-edit-group-done 'part 'group)))
-       (part (or part 'info))
-       (winconf (current-window-configuration))
-       info)
+  (let* ((part (or part 'info))
+        (done-func `(lambda ()
+                      "Exit editing mode and update the information."
+                      (interactive)
+                      (gnus-group-edit-group-done ',part ,group)))
+        (winconf (current-window-configuration))
+        info)
     (or group (error "No group on current line"))
     (or (setq info (gnus-get-info group))
        (error "Killed group; can't be edited"))
@@ -5138,19 +5711,16 @@ of the Earth\".  There is no undo."
     (local-set-key "\C-c\C-c" done-func)
     (make-local-variable 'gnus-prev-winconf)
     (setq gnus-prev-winconf winconf)
-    ;; We modify the func to let it know what part it is editing.
-    (setcar (cdr (nth 4 done-func)) (list 'quote part))
-    (setcar (cdr (cdr (nth 4 done-func))) group)
     (erase-buffer)
     (insert
-     (cond 
+     (cond
       ((eq part 'method)
        ";; Type `C-c C-c' after editing the select method.\n\n")
       ((eq part 'params)
        ";; Type `C-c C-c' after editing the group parameters.\n\n")
       ((eq part 'info)
        ";; Type `C-c C-c' after editing the group info.\n\n")))
-    (insert 
+    (insert
      (pp-to-string
       (cond ((eq part 'method)
             (or (gnus-info-method info) "native"))
@@ -5175,27 +5745,41 @@ of the Earth\".  There is no undo."
   (goto-char (point-min))
   (let* ((form (read (current-buffer)))
         (winconf gnus-prev-winconf)
-        (new-group (when (eq part 'info)
-                     (if (or (not (nth 4 form))
+        (method (cond ((eq part 'info) (nth 4 form))
+                      ((eq part 'method) form)
+                      (t nil)))
+        (info (cond ((eq part 'info) form)
+                    ((eq part 'method) (gnus-get-info group))
+                    (t nil)))
+        (new-group (if info
+                     (if (or (not method)
                              (gnus-server-equal
-                              gnus-select-method (nth 4 form)))
-                         (gnus-group-real-name (car form))
+                              gnus-select-method method))
+                         (gnus-group-real-name (car info))
                        (gnus-group-prefixed-name
-                        (gnus-group-real-name (car form)) (nth 4 form))))))
+                        (gnus-group-real-name (car info)) method))
+                     nil)))
+    (when (and new-group
+              (not (equal new-group group)))
+      (when (gnus-group-goto-group group)
+       (gnus-group-kill-group 1))
+      (gnus-activate-group new-group))
     ;; Set the info.
-    (if (eq part 'info) 
+    (if (and info new-group)
        (progn
-         (when new-group (setcar form new-group))
-         (gnus-group-set-info form))
-      (gnus-group-set-info form group part))
+         (setq info (gnus-copy-sequence info))
+         (setcar info new-group)
+         (unless (gnus-server-equal method "native")
+           (unless (nthcdr 3 info)
+             (nconc info (list nil nil)))
+           (unless (nthcdr 4 info)
+             (nconc info (list nil)))
+           (gnus-info-set-method info method))
+         (gnus-group-set-info info))
+      (gnus-group-set-info form (or new-group group) part))
     (kill-buffer (current-buffer))
     (and winconf (set-window-configuration winconf))
     (set-buffer gnus-group-buffer)
-    (when (and new-group 
-            (not (equal new-group group)))
-      (when (gnus-group-goto-group group)
-       (gnus-group-kill-group 1))
-      (gnus-activate-group new-group))
     (gnus-group-update-group (or new-group group))
     (gnus-group-position-point)))
 
@@ -5203,38 +5787,38 @@ of the Earth\".  There is no undo."
   "Create the Gnus documentation group."
   (interactive)
   (let ((path load-path)
-       (name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help")))
-       file dir)
+       (name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help")))
+       file dir)
     (and (gnus-gethash name gnus-newsrc-hashtb)
-        (error "Documentation group already exists"))
+        (error "Documentation group already exists"))
     (while path
       (setq dir (file-name-as-directory (expand-file-name (pop path)))
            file nil)
       (when (or (file-exists-p (setq file (concat dir "gnus-tut.txt")))
                (file-exists-p
-                (setq file (concat (file-name-directory 
+                (setq file (concat (file-name-directory
                                     (directory-file-name dir))
                                    "etc/gnus-tut.txt"))))
        (setq path nil)))
     (if (not file)
-       (message "Couldn't find doc group")
-      (gnus-group-make-group 
+       (gnus-message 1 "Couldn't find doc group")
+      (gnus-group-make-group
        (gnus-group-real-name name)
-       (list 'nndoc name
-            (list 'nndoc-address file)
-            (list 'nndoc-article-type 'mbox)))))
+       (list 'nndoc "gnus-help"
+            (list 'nndoc-address file)
+            (list 'nndoc-article-type 'mbox)))))
   (gnus-group-position-point))
 
 (defun gnus-group-make-doc-group (file type)
   "Create a group that uses a single file as the source."
-  (interactive 
-   (list (read-file-name "File name: ") 
+  (interactive
+   (list (read-file-name "File name: ")
         (and current-prefix-arg 'ask)))
   (when (eq type 'ask)
     (let ((err "")
          char found)
       (while (not found)
-       (message 
+       (message
         "%sFile type (mbox, babyl, digest, forward, mmfd, guess) [mbdfag]: "
         err)
        (setq found (cond ((= (setq char (read-char)) ?m) 'mbox)
@@ -5249,35 +5833,31 @@ of the Earth\".  There is no undo."
         (name (gnus-generate-new-group-name
                (gnus-group-prefixed-name
                 (file-name-nondirectory file) '(nndoc "")))))
-    (gnus-group-make-group 
+    (gnus-group-make-group
      (gnus-group-real-name name)
-     (list 'nndoc name
+     (list 'nndoc (file-name-nondirectory file)
           (list 'nndoc-address file)
-          (list 'nndoc-article-type (or type 'guess))))
-    (forward-line -1)
-    (gnus-group-position-point)))
+          (list 'nndoc-article-type (or type 'guess))))))
 
 (defun gnus-group-make-archive-group (&optional all)
   "Create the (ding) Gnus archive group of the most recent articles.
 Given a prefix, create a full group."
   (interactive "P")
-  (let ((group (gnus-group-prefixed-name 
+  (let ((group (gnus-group-prefixed-name
                (if all "ding.archives" "ding.recent") '(nndir ""))))
     (and (gnus-gethash group gnus-newsrc-hashtb)
         (error "Archive group already exists"))
     (gnus-group-make-group
      (gnus-group-real-name group)
      (list 'nndir (if all "hpc" "edu")
-          (list 'nndir-directory  
-                (if all gnus-group-archive-directory 
-                  gnus-group-recent-archive-directory)))))
-  (forward-line -1)
-  (gnus-group-position-point))
+          (list 'nndir-directory
+                (if all gnus-group-archive-directory
+                  gnus-group-recent-archive-directory))))))
 
 (defun gnus-group-make-directory-group (dir)
   "Create an nndir group.
 The user will be prompted for a directory.  The contents of this
-directory will be used as a newsgroup.  The directory should contain
+directory will be used as a newsgroup. The directory should contain
 mail messages or news articles in files that have numeric names."
   (interactive
    (list (read-file-name "Create group from directory: ")))
@@ -5288,16 +5868,14 @@ mail messages or news articles in files that have numeric names."
        group)
     (while (or (not group) (gnus-gethash group gnus-newsrc-hashtb))
       (setq group
-           (gnus-group-prefixed-name 
+           (gnus-group-prefixed-name
             (concat (file-name-as-directory (directory-file-name dir))
                     ext)
             '(nndir "")))
       (setq ext (format "<%d>" (setq i (1+ i)))))
-    (gnus-group-make-group 
+    (gnus-group-make-group
      (gnus-group-real-name group)
-     (list 'nndir group (list 'nndir-directory dir))))
-  (forward-line -1)
-  (gnus-group-position-point))
+     (list 'nndir group (list 'nndir-directory dir)))))
 
 (defun gnus-group-make-kiboze-group (group address scores)
   "Create an nnkiboze group.
@@ -5312,24 +5890,19 @@ score file entries for articles to include in the group."
                             "references" "chars" "lines" "xref"
                             "followup" "all" "body" "head")))
          scores header regexp regexps)
-      (while (not (equal "" (setq header (completing-read 
+      (while (not (equal "" (setq header (completing-read
                                          "Match on header: " headers nil t))))
        (setq regexps nil)
-       (while (not (equal "" (setq regexp (read-string 
+       (while (not (equal "" (setq regexp (read-string
                                            (format "Match on %s (string): "
                                                    header)))))
          (setq regexps (cons (list regexp nil nil 'r) regexps)))
        (setq scores (cons (cons header regexps) scores)))
       scores)))
   (gnus-group-make-group group "nnkiboze" address)
-  (save-excursion
-    (gnus-set-work-buffer)
+  (nnheader-temp-write (gnus-score-file-name (concat "nnkiboze:" group))
     (let (emacs-lisp-mode-hook)
-      (pp scores (current-buffer)))
-    (write-region (point-min) (point-max) 
-                 (gnus-score-file-name (concat "nnkiboze:" group))))
-  (forward-line -1)
-  (gnus-group-position-point))
+      (pp scores (current-buffer)))))
 
 (defun gnus-group-add-to-virtual (n vgroup)
   "Add the current group to a virtual group."
@@ -5342,10 +5915,10 @@ score file entries for articles to include in the group."
   (let* ((groups (gnus-group-process-prefix n))
         (method (gnus-info-method (gnus-get-info vgroup))))
     (setcar (cdr method)
-           (concat 
+           (concat
             (nth 1 method) "\\|"
-            (mapconcat 
-             (lambda (s) 
+            (mapconcat
+             (lambda (s)
                (gnus-group-remove-mark s)
                (concat "\\(^" (regexp-quote s) "$\\)"))
              groups "\\|"))))
@@ -5374,7 +5947,7 @@ score file entries for articles to include in the group."
                method))
         (name (gnus-generate-new-group-name leaf)))
     (let ((nneething-read-only t))
-      (or (gnus-group-read-ephemeral-group 
+      (or (gnus-group-read-ephemeral-group
           name method t
           (cons (current-buffer) (if (eq major-mode 'gnus-summary-mode)
                                      'summary 'group)))
@@ -5388,20 +5961,25 @@ score file entries for articles to include in the group."
 If REVERSE, reverse the sorting order."
   (interactive (list gnus-group-sort-function
                     current-prefix-arg))
-  (unless (listp func)
-    (setq func (list func)))
-  ;; We peel off the dummy group from the alist.
-  (when (equal (car (gnus-info-group gnus-newsrc-alist)) "dummy.group")
-    (pop gnus-newsrc-alist))
-  ;; Do the sorting.
-  (while func
-    (setq gnus-newsrc-alist 
-         (sort gnus-newsrc-alist (pop func))))
-  (when reverse
-    (setq gnus-newsrc-alist (nreverse gnus-newsrc-alist)))
-  ;; Regenerate the hash table.
-  (gnus-make-hashtable-from-newsrc-alist)
-  (gnus-group-list-groups))
+  (let ((func (cond 
+              ((not (listp func)) func)
+              ((null func) func)
+              ((= 1 (length func)) (car func))
+              (t `(lambda (t1 t2)
+                    ,(gnus-make-sort-function 
+                      (reverse func)))))))
+    ;; We peel off the dummy group from the alist.
+    (when func
+      (when (equal (car (gnus-info-group gnus-newsrc-alist)) "dummy.group")
+       (pop gnus-newsrc-alist))
+      ;; Do the sorting.
+      (setq gnus-newsrc-alist
+           (sort gnus-newsrc-alist func))
+      (when reverse
+       (setq gnus-newsrc-alist (nreverse gnus-newsrc-alist)))
+      ;; Regenerate the hash table.
+      (gnus-make-hashtable-from-newsrc-alist)
+      (gnus-group-list-groups))))
 
 (defun gnus-group-sort-groups-by-alphabet (&optional reverse)
   "Sort the group buffer alphabetically by group name.
@@ -5458,7 +6036,7 @@ If REVERSE, sort in reverse order."
   "Sort alphabetically by backend name."
   (string< (symbol-name (car (gnus-find-method-for-group
                              (gnus-info-group info1) info1)))
-          (symbol-name (car (gnus-find-method-for-group 
+          (symbol-name (car (gnus-find-method-for-group
                              (gnus-info-group info2) info2)))))
 
 (defun gnus-group-sort-by-score (info1 info2)
@@ -5471,10 +6049,25 @@ If REVERSE, sort in reverse order."
        (level2 (gnus-info-level info2)))
     (or (< level1 level2)
        (and (= level1 level2)
-            (< (gnus-info-score info1) (gnus-info-score info2))))))
+            (> (gnus-info-score info1) (gnus-info-score info2))))))
 
 ;; Group catching up.
 
+(defun gnus-group-clear-data (n)
+  "Clear all marks and read ranges from the current group."
+  (interactive "P")
+  (let ((groups (gnus-group-process-prefix n))
+       group info)
+    (while (setq group (pop groups))
+      (setq info (gnus-get-info group))
+      (gnus-info-set-read info nil)
+      (when (gnus-info-marks info)
+       (gnus-info-set-marks info nil))
+      (gnus-get-unread-articles-in-group info (gnus-active group) t)
+      (when (gnus-group-goto-group group)
+       (gnus-group-remove-mark group)
+       (gnus-group-update-group-line)))))
+
 (defun gnus-group-catchup-current (&optional n all)
   "Mark all articles not marked as unread in current newsgroup as read.
 If prefix argument N is numeric, the ARG next newsgroups will be
@@ -5483,6 +6076,8 @@ read.  Cross references (Xref: header) of articles are ignored.
 The difference between N and actual number of newsgroups that were
 caught up is returned."
   (interactive "P")
+  (unless (gnus-group-group-name)
+    (error "No group on the current line"))
   (if (not (or (not gnus-interactive-catchup) ;Without confirmation?
               gnus-expert-user
               (gnus-y-or-n-p
@@ -5493,17 +6088,19 @@ caught up is returned."
     (let ((groups (gnus-group-process-prefix n))
          (ret 0))
       (while groups
-       ;; Virtual groups have to be given special treatment. 
+       ;; Virtual groups have to be given special treatment.
        (let ((method (gnus-find-method-for-group (car groups))))
          (if (eq 'nnvirtual (car method))
              (nnvirtual-catchup-group
               (gnus-group-real-name (car groups)) (nth 1 method) all)))
        (gnus-group-remove-mark (car groups))
-       (if (prog1
-               (gnus-group-goto-group (car groups))
-             (gnus-group-catchup (car groups) all))
-           (gnus-group-update-group-line)
-         (setq ret (1+ ret)))
+       (if (>= (gnus-group-group-level) gnus-level-zombie)
+           (gnus-message 2 "Dead groups can't be caught up")
+         (if (prog1
+                 (gnus-group-goto-group (car groups))
+               (gnus-group-catchup (car groups) all))
+             (gnus-group-update-group-line)
+           (setq ret (1+ ret))))
        (setq groups (cdr groups)))
       (gnus-group-next-unread-group 1)
       ret)))
@@ -5526,20 +6123,21 @@ or nil if no action could be taken."
        (gnus-message 1 "Can't catch up; non-active group")
       ;; Do auto-expirable marks if that's required.
       (when (gnus-group-auto-expirable-p group)
-       (gnus-add-marked-articles 
+       (gnus-add-marked-articles
         group 'expire (gnus-list-of-unread-articles group))
        (when all
          (let ((marks (nth 3 (nth 2 entry))))
-           (gnus-add-marked-articles 
+           (gnus-add-marked-articles
             group 'expire (gnus-uncompress-range (cdr (assq 'tick marks))))
-           (gnus-add-marked-articles 
+           (gnus-add-marked-articles
             group 'expire (gnus-uncompress-range (cdr (assq 'tick marks)))))))
       (when entry
        (gnus-update-read-articles group nil)
-       ;; Also nix out the lists of marks and dormants. 
-       (when all 
+       ;; Also nix out the lists of marks and dormants.
+       (when all
          (gnus-add-marked-articles group 'tick nil nil 'force)
          (gnus-add-marked-articles group 'dormant nil nil 'force))
+       (run-hooks 'gnus-group-catchup-group-hook)
        num))))
 
 (defun gnus-group-expire-articles (&optional n)
@@ -5549,26 +6147,32 @@ or nil if no action could be taken."
        group)
     (unless groups
       (error "No groups to expire"))
-    (while groups
-      (setq group (pop groups))
+    (while (setq group (pop groups))
       (gnus-group-remove-mark group)
       (when (gnus-check-backend-function 'request-expire-articles group)
+       (gnus-message 6 "Expiring articles in %s..." group)
        (let* ((info (gnus-get-info group))
               (expirable (if (gnus-group-total-expirable-p group)
                              (cons nil (gnus-list-of-read-articles group))
                            (assq 'expire (gnus-info-marks info))))
               (expiry-wait (gnus-group-get-parameter group 'expiry-wait)))
-         (when expirable 
-           (setcdr expirable
-                   (gnus-compress-sequence
-                    (if expiry-wait
-                        (let ((nnmail-expiry-wait-function nil)
-                              (nnmail-expiry-wait expiry-wait))
-                          (gnus-request-expire-articles 
-                           (gnus-uncompress-sequence (cdr expirable)) group))
-                      (gnus-request-expire-articles 
-                       (gnus-uncompress-sequence (cdr expirable))
-                       group))))))))))
+         (when expirable
+           (setcdr
+            expirable
+            (gnus-compress-sequence
+             (if expiry-wait
+                 ;; We set the expiry variables to the groupp
+                 ;; parameter. 
+                 (let ((nnmail-expiry-wait-function nil)
+                       (nnmail-expiry-wait expiry-wait))
+                   (gnus-request-expire-articles
+                    (gnus-uncompress-sequence (cdr expirable)) group))
+               ;; Just expire using the normal expiry values.
+               (gnus-request-expire-articles
+                (gnus-uncompress-sequence (cdr expirable)) group))))
+           (gnus-close-group group))
+         (gnus-message 6 "Expiring articles in %s...done" group)))
+      (gnus-group-position-point))))
 
 (defun gnus-group-expire-all-groups ()
   "Expire all expirable articles in all newsgroups."
@@ -5583,27 +6187,29 @@ or nil if no action could be taken."
 
 (defun gnus-group-set-current-level (n level)
   "Set the level of the next N groups to LEVEL."
-  (interactive 
+  (interactive
    (list
     current-prefix-arg
     (string-to-int
-     (let ((s (read-string 
-              (format "Level (default %s): " (gnus-group-group-level)))))
+     (let ((s (read-string
+              (format "Level (default %s): "
+                      (or (gnus-group-group-level) 
+                          gnus-level-default-subscribed)))))
        (if (string-match "^\\s-*$" s)
-          (int-to-string (gnus-group-group-level))
+          (int-to-string (or (gnus-group-group-level) 
+                             gnus-level-default-subscribed))
         s)))))
   (or (and (>= level 1) (<= level gnus-level-killed))
       (error "Illegal level: %d" level))
   (let ((groups (gnus-group-process-prefix n))
        group)
-    (while groups
-      (setq group (car groups)
-           groups (cdr groups))
+    (while (setq group (pop groups))
       (gnus-group-remove-mark group)
-      (gnus-message 6 "Changed level of %s from %d to %d" 
-                   group (gnus-group-group-level) level)
-      (gnus-group-change-level group level
-                              (gnus-group-group-level))
+      (gnus-message 6 "Changed level of %s from %d to %d"
+                   group (or (gnus-group-group-level) gnus-level-killed)
+                   level)
+      (gnus-group-change-level
+       group level (or (gnus-group-group-level) gnus-level-killed))
       (gnus-group-update-group-line)))
   (gnus-group-position-point))
 
@@ -5630,30 +6236,32 @@ Killed newsgroups are subscribed.  If SILENT, don't try to update the
 group line."
   (interactive
    (list (completing-read
-         "Group: " gnus-active-hashtb nil 
-         (memq gnus-select-method gnus-have-read-active-file))))
+         "Group: " gnus-active-hashtb nil
+         (gnus-read-active-file-p)
+         nil 
+         'gnus-group-history)))
   (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb)))
     (cond
      ((string-match "^[ \t]$" group)
       (error "Empty group name"))
      (newsrc
       ;; Toggle subscription flag.
-      (gnus-group-change-level 
-       newsrc (if level level (if (<= (nth 1 (nth 2 newsrc)) 
-                                     gnus-level-subscribed) 
+      (gnus-group-change-level
+       newsrc (if level level (if (<= (nth 1 (nth 2 newsrc))
+                                     gnus-level-subscribed)
                                  (1+ gnus-level-subscribed)
                                gnus-level-default-subscribed)))
       (unless silent
        (gnus-group-update-group group)))
      ((and (stringp group)
-          (or (not (memq gnus-select-method gnus-have-read-active-file))
+          (or (not (gnus-read-active-file-p))
               (gnus-active group)))
       ;; Add new newsgroup.
-      (gnus-group-change-level 
-       group 
-       (if level level gnus-level-default-subscribed) 
-       (or (and (member group gnus-zombie-list) 
-               gnus-level-zombie) 
+      (gnus-group-change-level
+       group
+       (if level level gnus-level-default-subscribed)
+       (or (and (member group gnus-zombie-list)
+               gnus-level-zombie)
           gnus-level-killed)
        (and (gnus-group-group-name)
            (gnus-gethash (gnus-group-group-name) gnus-newsrc-hashtb)))
@@ -5664,8 +6272,8 @@ group line."
 
 (defun gnus-group-transpose-groups (n)
   "Move the current newsgroup up N places.
-If given a negative prefix, move down instead.  The difference between
-N and the number of steps taken is returned." 
+If given a negative prefix, move down instead. The difference between
+N and the number of steps taken is returned."
   (interactive "p")
   (or (gnus-group-group-name)
       (error "No group on current line"))
@@ -5705,7 +6313,7 @@ The killed newsgroups can be yanked by using \\[gnus-group-yank-group]."
 (defun gnus-group-kill-group (&optional n discard)
   "Kill the next N groups.
 The killed newsgroups can be yanked by using \\[gnus-group-yank-group].
-However, only groups that were alive can be yanked; already killed 
+However, only groups that were alive can be yanked; already killed
 groups or zombie groups can't be yanked.
 The return value is the name of the group that was killed, or a list
 of groups killed."
@@ -5720,26 +6328,34 @@ of groups killed."
          (gnus-group-remove-mark group)
          (setq level (gnus-group-group-level))
          (gnus-delete-line)
-         (if (and (not discard)
-                  (setq entry (gnus-gethash group gnus-newsrc-hashtb)))
-             (setq gnus-list-of-killed-groups 
-                   (cons (cons (car entry) (nth 2 entry)) 
-                         gnus-list-of-killed-groups)))
-         (gnus-group-change-level 
+         (when (and (not discard)
+                    (setq entry (gnus-gethash group gnus-newsrc-hashtb)))
+           (push (cons (car entry) (nth 2 entry))
+                 gnus-list-of-killed-groups))
+         (gnus-group-change-level
           (if entry entry group) gnus-level-killed (if entry nil level)))
       ;; If there are lots and lots of groups to be killed, we use
       ;; this thing instead.
       (let (entry)
        (setq groups (nreverse groups))
        (while groups
-         (gnus-group-remove-mark (car groups))
+         (gnus-group-remove-mark (setq group (pop groups)))
          (gnus-delete-line)
-         (setq entry (gnus-gethash (pop groups) gnus-newsrc-hashtb))
-         (push (cons (car entry) (nth 2 entry))
-               gnus-list-of-killed-groups)
-         (setcdr (cdr entry) (cdr (cdr (cdr entry)))))
+         (push group gnus-killed-list)
+         (setq gnus-newsrc-alist
+               (delq (assoc group gnus-newsrc-alist)
+                     gnus-newsrc-alist))
+         (when gnus-group-change-level-function
+           (funcall gnus-group-change-level-function group 9 3))
+         (cond
+          ((setq entry (gnus-gethash group gnus-newsrc-hashtb))
+           (push (cons (car entry) (nth 2 entry))
+                 gnus-list-of-killed-groups)
+           (setcdr (cdr entry) (cdddr entry)))
+          ((member group gnus-zombie-list)
+           (setq gnus-zombie-list (delete group gnus-zombie-list)))))
        (gnus-make-hashtable-from-newsrc-alist)))
-    
+
     (gnus-group-position-point)
     (if (< (length out) 2) (car out) (nreverse out))))
 
@@ -5761,8 +6377,8 @@ is returned."
       ;; other newsgroups in this buffer, just make this newsgroup the
       ;; first newsgroup.
       (setq prev (gnus-group-group-name))
-      (gnus-group-change-level 
-       info (nth 2 info) gnus-level-killed 
+      (gnus-group-change-level
+       info (gnus-info-level (cdr info)) gnus-level-killed
        (and prev (gnus-gethash prev gnus-newsrc-hashtb))
        t)
       (gnus-group-insert-group-line-info group))
@@ -5773,7 +6389,7 @@ is returned."
 (defun gnus-group-kill-level (level)
   "Kill all groups that is on a certain LEVEL."
   (interactive "nKill all groups on level: ")
-  (cond 
+  (cond
    ((= level gnus-level-zombie)
     (setq gnus-killed-list
          (nconc gnus-zombie-list gnus-killed-list))
@@ -5782,7 +6398,7 @@ is returned."
         (> level 0)
         (or gnus-expert-user
             (gnus-yes-or-no-p
-             (format 
+             (format
               "Do you really want to kill all groups on level %d? "
               level))))
     (let* ((prev gnus-newsrc-alist)
@@ -5796,7 +6412,7 @@ is returned."
       (gnus-group-list-groups)))
    (t
     (error "Can't kill; illegal level: %d" level))))
-      
+
 (defun gnus-group-list-all-groups (&optional arg)
   "List all newsgroups with level ARG or lower.
 Default is gnus-level-unsubscribed, which lists all subscribed and most
@@ -5813,32 +6429,11 @@ entail asking the server for the groups."
   (interactive "P")
   ;; Find all possible killed newsgroups if arg.
   (when arg
-    ;; First make sure active file has been read.
-    (unless gnus-have-read-active-file
-      (let ((gnus-read-active-file t))
-       (gnus-read-active-file)))
-    (or gnus-killed-hashtb (gnus-make-hashtable-from-killed))
-    ;; Go through all newsgroups that are known to Gnus - enlarge kill list
-    (mapatoms
-     (lambda (sym)
-       (let ((groups 0)
-            (group (symbol-name sym)))
-        (if (or (null group)
-                (gnus-gethash group gnus-killed-hashtb)
-                (gnus-gethash group gnus-newsrc-hashtb))
-            ()
-          (let ((do-sub (gnus-matches-options-n group)))
-            (if (or (eq do-sub 'subscribe) (eq do-sub 'ignore))
-                ()
-              (setq groups (1+ groups))
-              (setq gnus-killed-list 
-                    (cons group gnus-killed-list))
-              (gnus-sethash group group gnus-killed-hashtb))))))
-     gnus-active-hashtb))
+    (gnus-get-killed-groups))
   (if (not gnus-killed-list)
       (gnus-message 6 "No killed groups")
     (let (gnus-group-list-mode)
-      (funcall gnus-group-prepare-function 
+      (funcall gnus-group-prepare-function
               gnus-level-killed t gnus-level-killed))
     (goto-char (point-min)))
   (gnus-group-position-point))
@@ -5857,17 +6452,18 @@ entail asking the server for the groups."
 (defun gnus-group-list-active ()
   "List all groups that are available from the server(s)."
   (interactive)
-  ;; First we make sure that we have really read the active file. 
-  (unless gnus-have-read-active-file
+  ;; First we make sure that we have really read the active file.
+  (unless (gnus-read-active-file-p)
     (let ((gnus-read-active-file t))
       (gnus-read-active-file)))
   ;; Find all groups and sort them.
-  (let ((groups 
-        (sort 
+  (let ((groups
+        (sort
          (let (list)
            (mapatoms
             (lambda (sym)
-              (and (symbol-value sym)
+              (and (boundp sym)
+                   (symbol-value sym)
                    (setq list (cons (symbol-name sym) list))))
             gnus-active-hashtb)
            list)
@@ -5875,8 +6471,7 @@ entail asking the server for the groups."
        (buffer-read-only nil))
     (erase-buffer)
     (while groups
-      (gnus-group-insert-group-line-info (car groups))
-      (setq groups (cdr groups)))
+      (gnus-group-insert-group-line-info (pop groups)))
     (goto-char (point-min))))
 
 (defun gnus-activate-all-groups (level)
@@ -5894,14 +6489,14 @@ re-scanning.  If ARG is non-nil and not a number, this will force
   (interactive "P")
   (run-hooks 'gnus-get-new-news-hook)
   ;; We might read in new NoCeM messages here.
-  (and gnus-use-nocem (gnus-nocem-scan-groups))
+  (when (and gnus-use-nocem 
+            (null arg))
+    (gnus-nocem-scan-groups))
   ;; If ARG is not a number, then we read the active file.
-  (and arg
-       (not (numberp arg))
-       (progn
-        (let ((gnus-read-active-file t))
-          (gnus-read-active-file))
-        (setq arg nil)))
+  (when (and arg (not (numberp arg)))
+    (let ((gnus-read-active-file t))
+      (gnus-read-active-file))
+    (setq arg nil))
 
   (setq arg (gnus-group-default-level arg t))
   (if (and gnus-read-active-file (not arg))
@@ -5910,6 +6505,7 @@ re-scanning.  If ARG is non-nil and not a number, this will force
        (gnus-get-unread-articles arg))
     (let ((gnus-read-active-file (if arg nil gnus-read-active-file)))
       (gnus-get-unread-articles arg)))
+  (run-hooks 'gnus-after-getting-new-news-hook)
   (gnus-group-list-groups))
 
 (defun gnus-group-get-new-news-this-group (&optional n)
@@ -5919,64 +6515,64 @@ If N is negative, this group and the N-1 previous groups will be checked."
   (interactive "P")
   (let* ((groups (gnus-group-process-prefix n))
         (ret (if (numberp n) (- n (length groups)) 0))
+        (beg (unless n (point)))
         group)
-    (while groups
-      (setq group (car groups)
-           groups (cdr groups))
+    (while (setq group (pop groups))
       (gnus-group-remove-mark group)
-      (or (gnus-get-new-news-in-group group)
-         (progn 
-           (ding) 
-           (message "%s error: %s" group (gnus-status-message group))
-           (sit-for 2))))
-    (gnus-group-next-unread-group 1 t)
+      (if (gnus-activate-group group 'scan)
+         (progn
+           (gnus-get-unread-articles-in-group
+            (gnus-get-info group) (gnus-active group) t)
+           (unless (gnus-virtual-group-p group)
+             (gnus-close-group group))
+           (gnus-group-update-group group))
+       (gnus-error 3 "%s error: %s" group (gnus-status-message group))))
+    (when beg (goto-char beg))
+    (when gnus-goto-next-group-when-activating
+      (gnus-group-next-unread-group 1 t))
     (gnus-summary-position-point)
     ret))
 
-(defun gnus-get-new-news-in-group (group)
-  (when (and group (gnus-activate-group group 'scan))
-    (gnus-get-unread-articles-in-group 
-     (gnus-get-info group) (gnus-active group))
-    (when (gnus-group-goto-group group)
-      (gnus-group-update-group-line))
-    t))
-
 (defun gnus-group-fetch-faq (group &optional faq-dir)
   "Fetch the FAQ for the current group."
-  (interactive 
+  (interactive
    (list
-    (gnus-group-real-name (gnus-group-group-name))
+    (and (gnus-group-group-name)
+        (gnus-group-real-name (gnus-group-group-name)))
     (cond (current-prefix-arg
-          (completing-read 
-           "Faq dir: " (and (listp gnus-group-faq-directory) 
-                            gnus-group-faq-directory))))))
+          (completing-read
+           "Faq dir: " (and (listp gnus-group-faq-directory)
+                            (mapcar (lambda (file) (list file))
+                                    gnus-group-faq-directory)))))))
   (or faq-dir
       (setq faq-dir (if (listp gnus-group-faq-directory)
-                        (car gnus-group-faq-directory)
-                      gnus-group-faq-directory)))
+                       (car gnus-group-faq-directory)
+                     gnus-group-faq-directory)))
   (or group (error "No group name given"))
   (let ((file (concat (file-name-as-directory faq-dir)
                      (gnus-group-real-name group))))
     (if (not (file-exists-p file))
        (error "No such file: %s" file)
       (find-file file))))
-  
+
 (defun gnus-group-describe-group (force &optional group)
   "Display a description of the current newsgroup."
   (interactive (list current-prefix-arg (gnus-group-group-name)))
-  (and force (setq gnus-description-hashtb nil))
+  (when (and force
+            gnus-description-hashtb)
+    (gnus-sethash group nil gnus-description-hashtb))
   (let ((method (gnus-find-method-for-group group))
        desc)
     (or group (error "No group name given"))
     (and (or (and gnus-description-hashtb
                  ;; We check whether this group's method has been
-                 ;; queried for a description file.  
-                 (gnus-gethash 
-                  (gnus-group-prefixed-name "" method) 
+                 ;; queried for a description file.
+                 (gnus-gethash
+                  (gnus-group-prefixed-name "" method)
                   gnus-description-hashtb))
             (setq desc (gnus-group-get-description group))
             (gnus-read-descriptions-file method))
-        (message
+        (gnus-message 1
          (or desc (gnus-gethash group gnus-description-hashtb)
              "No description available")))))
 
@@ -5996,7 +6592,7 @@ If N is negative, this group and the N-1 previous groups will be checked."
        (setq b (point))
        (insert (format "      *: %-20s %s\n" (symbol-name group)
                       (symbol-value group)))
-       (add-text-properties 
+       (gnus-add-text-properties
        b (1+ b) (list 'gnus-group group
                       'gnus-unread t 'gnus-marked nil
                       'gnus-level (1+ gnus-level-subscribed))))
@@ -6012,20 +6608,20 @@ If N is negative, this group and the N-1 previous groups will be checked."
        (obuf (current-buffer))
        groups des)
     ;; Go through all newsgroups that are known to Gnus.
-    (mapatoms 
+    (mapatoms
      (lambda (group)
        (and (symbol-name group)
            (string-match regexp (symbol-name group))
            (setq groups (cons (symbol-name group) groups))))
      gnus-active-hashtb)
-    ;; Go through all descriptions that are known to Gnus. 
-    (if search-description
-       (mapatoms 
-        (lambda (group)
-          (and (string-match regexp (symbol-value group))
-               (gnus-active (symbol-name group))
-               (setq groups (cons (symbol-name group) groups))))
-        gnus-description-hashtb))
+    ;; Also go through all descriptions that are known to Gnus.
+    (when search-description
+      (mapatoms
+       (lambda (group)
+        (and (string-match regexp (symbol-value group))
+             (gnus-active (symbol-name group))
+             (setq groups (cons (symbol-name group) groups))))
+       gnus-description-hashtb))
     (if (not groups)
        (gnus-message 3 "No groups matched \"%s\"." regexp)
       ;; Print out all the groups.
@@ -6040,7 +6636,7 @@ If N is negative, this group and the N-1 previous groups will be checked."
              (progn
                (insert (setq prev (car groups)) "\n")
                (if (and gnus-description-hashtb
-                        (setq des (gnus-gethash (car groups) 
+                        (setq des (gnus-gethash (car groups)
                                                 gnus-description-hashtb)))
                    (insert "  " des "\n"))))
          (setq groups (cdr groups)))
@@ -6056,22 +6652,28 @@ If N is negative, this group and the N-1 previous groups will be checked."
   (gnus-group-apropos regexp t))
 
 ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
-(defun gnus-group-list-matching (level regexp &optional all lowest) 
+(defun gnus-group-list-matching (level regexp &optional all lowest)
   "List all groups with unread articles that match REGEXP.
 If the prefix LEVEL is non-nil, it should be a number that says which
-level to cut off listing groups. 
+level to cut off listing groups.
 If ALL, also list groups with no unread articles.
-If LOWEST, don't list groups with level lower than LOWEST."
+If LOWEST, don't list groups with level lower than LOWEST.
+
+This command may read the active file."
   (interactive "P\nsList newsgroups matching: ")
+  ;; First make sure active file has been read.
+  (when (and level
+            (> (prefix-numeric-value level) gnus-level-killed))
+    (gnus-get-killed-groups))
   (gnus-group-prepare-flat (or level gnus-level-subscribed)
                           all (or lowest 1) regexp)
   (goto-char (point-min))
   (gnus-group-position-point))
 
-(defun gnus-group-list-all-matching (level regexp &optional lowest) 
+(defun gnus-group-list-all-matching (level regexp &optional lowest)
   "List all groups that match REGEXP.
 If the prefix LEVEL is non-nil, it should be a number that says which
-level to cut off listing groups. 
+level to cut off listing groups.
 If LOWEST, don't list groups with level lower than LOWEST."
   (interactive "P\nsList newsgroups matching: ")
   (gnus-group-list-matching (or level gnus-level-killed) regexp t lowest))
@@ -6086,9 +6688,12 @@ If FORCE, force saving whether it is necessary or not."
 (defun gnus-group-restart (&optional arg)
   "Force Gnus to read the .newsrc file."
   (interactive "P")
-  (gnus-save-newsrc-file)
-  (gnus-setup-news 'force)
-  (gnus-group-list-groups arg))
+  (when (gnus-yes-or-no-p
+        (format "Are you sure you want to read %s? "
+                gnus-current-startup-file))
+    (gnus-save-newsrc-file)
+    (gnus-setup-news 'force)
+    (gnus-group-list-groups arg)))
 
 (defun gnus-group-read-init-file ()
   "Read the Gnus elisp init file."
@@ -6109,7 +6714,7 @@ If GROUP, edit that local kill file instead."
   (interactive "P")
   (setq gnus-current-kill-article article)
   (gnus-kill-file-edit-file group)
-  (gnus-message 
+  (gnus-message
    6
    (substitute-command-keys
     (format "Editing a %s kill file (Type \\[gnus-kill-file-exit] to exit)"
@@ -6132,19 +6737,18 @@ The hook gnus-suspend-gnus-hook is called before actually suspending."
   (interactive)
   (run-hooks 'gnus-suspend-gnus-hook)
   ;; Kill Gnus buffers except for group mode buffer.
-  (let ((group-buf (get-buffer gnus-group-buffer)))
-    ;; Do this on a separate list in case the user does a ^G before we finish
-    (let ((gnus-buffer-list
-          (delq group-buf (delq gnus-dribble-buffer
-                                (append gnus-buffer-list nil)))))
-      (while gnus-buffer-list
-       (gnus-kill-buffer (car gnus-buffer-list))
-       (setq gnus-buffer-list (cdr gnus-buffer-list))))
-    (if group-buf
-       (progn
-         (setq gnus-buffer-list (list group-buf))
-         (bury-buffer group-buf)
-         (delete-windows-on group-buf t)))))
+  (let* ((group-buf (get-buffer gnus-group-buffer))
+        ;; Do this on a separate list in case the user does a ^G before we finish
+        (gnus-buffer-list
+         (delete group-buf (delete gnus-dribble-buffer
+                                   (append gnus-buffer-list nil)))))
+    (while gnus-buffer-list
+      (gnus-kill-buffer (pop gnus-buffer-list)))
+    (gnus-kill-gnus-frames)
+    (when group-buf
+      (setq gnus-buffer-list (list group-buf))
+      (bury-buffer group-buf)
+      (delete-windows-on group-buf t))))
 
 (defun gnus-group-clear-dribble ()
   "Clear all information from the dribble buffer."
@@ -6156,31 +6760,29 @@ The hook gnus-suspend-gnus-hook is called before actually suspending."
   "Quit reading news after updating .newsrc.eld and .newsrc.
 The hook `gnus-exit-gnus-hook' is called before actually exiting."
   (interactive)
-  (if (or noninteractive               ;For gnus-batch-kill
-         (not (gnus-server-opened gnus-select-method)) ;NNTP connection closed
+  (when 
+      (or noninteractive               ;For gnus-batch-kill
          (not gnus-interactive-exit)   ;Without confirmation
          gnus-expert-user
          (gnus-y-or-n-p "Are you sure you want to quit reading news? "))
-      (progn
-       (run-hooks 'gnus-exit-gnus-hook)
-       ;; Offer to save data from non-quitted summary buffers.
-       (gnus-offer-save-summaries)
-       ;; Save the newsrc file(s).
-       (gnus-save-newsrc-file)
-       ;; Kill-em-all.
-       (gnus-close-backends)
-       ;; Shut down the cache.
-       (when gnus-use-cache
-         (gnus-cache-open))
-       ;; Reset everything.
-       (gnus-clear-system))))
+    (run-hooks 'gnus-exit-gnus-hook)
+    ;; Offer to save data from non-quitted summary buffers.
+    (gnus-offer-save-summaries)
+    ;; Save the newsrc file(s).
+    (gnus-save-newsrc-file)
+    ;; Kill-em-all.
+    (gnus-close-backends)
+    ;; Reset everything.
+    (gnus-clear-system)
+    ;; Allow the user to do things after cleaning up.
+    (run-hooks 'gnus-after-exiting-gnus-hook)))
 
 (defun gnus-close-backends ()
-  ;; Send a close request to all backends that support such a request. 
+  ;; Send a close request to all backends that support such a request.
   (let ((methods gnus-valid-select-methods)
        func)
     (while methods
-      (if (fboundp (setq func (intern (concat (car (car methods))
+      (if (fboundp (setq func (intern (concat (caar methods)
                                              "-request-close"))))
          (funcall func))
       (setq methods (cdr methods)))))
@@ -6203,15 +6805,14 @@ The hook `gnus-exit-gnus-hook' is called before actually exiting."
       (gnus-remove-some-windows))
     (gnus-dribble-save)
     (gnus-close-backends)
-    ;; Shut down the cache.
-    (when gnus-use-cache
-      (gnus-cache-open))
-    (gnus-clear-system)))
+    (gnus-clear-system)
+    ;; Allow the user to do things after cleaning up.
+    (run-hooks 'gnus-after-exiting-gnus-hook)))
 
 (defun gnus-offer-save-summaries ()
   "Offer to save all active summary buffers."
   (save-excursion
-    (let ((buflist (buffer-list)) 
+    (let ((buflist (buffer-list))
          buffers bufname)
       ;; Go through all buffers and find all summaries.
       (while buflist
@@ -6227,7 +6828,7 @@ The hook `gnus-exit-gnus-hook' is called before actually exiting."
        (setq buflist (cdr buflist)))
       ;; Go through all these summary buffers and offer to save them.
       (when buffers
-       (map-y-or-n-p 
+       (map-y-or-n-p
         "Update summary buffer %s? "
         (lambda (buf) (set-buffer buf) (gnus-summary-exit))
         buffers)))))
@@ -6240,585 +6841,320 @@ The hook `gnus-exit-gnus-hook' is called before actually exiting."
 (defun gnus-group-browse-foreign-server (method)
   "Browse a foreign news server.
 If called interactively, this function will ask for a select method
- (nntp, nnspool, etc.) and a server address (eg. nntp.some.where). 
+ (nntp, nnspool, etc.) and a server address (eg. nntp.some.where).
 If not, METHOD should be a list where the first element is the method
 and the second element is the address."
   (interactive
-   (list (let ((how (completing-read 
+   (list (let ((how (completing-read
                     "Which backend: "
                     (append gnus-valid-select-methods gnus-server-alist)
-                    nil t "nntp")))
+                    nil t (cons "nntp" 0) 'gnus-method-history)))
           ;; We either got a backend name or a virtual server name.
           ;; If the first, we also need an address.
           (if (assoc how gnus-valid-select-methods)
               (list (intern how)
                     ;; Suggested by mapjph@bath.ac.uk.
-                    (completing-read 
-                     "Address: " 
+                    (completing-read
+                     "Address: "
                      (mapcar (lambda (server) (list server))
                              gnus-secondary-servers)))
             ;; We got a server name, so we find the method.
             (gnus-server-to-method how)))))
   (gnus-browse-foreign-server method))
 
-\f
-;;;
-;;; Browse Server Mode
-;;;
-
-(defvar gnus-browse-mode-hook nil)
-(defvar gnus-browse-mode-map nil)
-(put 'gnus-browse-mode 'mode-class 'special)
-
-(if gnus-browse-mode-map
-    nil
-  (setq gnus-browse-mode-map (make-keymap))
-  (suppress-keymap gnus-browse-mode-map)
-  (define-key gnus-browse-mode-map " " 'gnus-browse-read-group)
-  (define-key gnus-browse-mode-map "=" 'gnus-browse-select-group)
-  (define-key gnus-browse-mode-map "n" 'gnus-browse-next-group)
-  (define-key gnus-browse-mode-map "p" 'gnus-browse-prev-group)
-  (define-key gnus-browse-mode-map "\177" 'gnus-browse-prev-group)
-  (define-key gnus-browse-mode-map "N" 'gnus-browse-next-group)
-  (define-key gnus-browse-mode-map "P" 'gnus-browse-prev-group)
-  (define-key gnus-browse-mode-map "\M-n" 'gnus-browse-next-group)
-  (define-key gnus-browse-mode-map "\M-p" 'gnus-browse-prev-group)
-  (define-key gnus-browse-mode-map "\r" 'gnus-browse-select-group)
-  (define-key gnus-browse-mode-map "u" 'gnus-browse-unsubscribe-current-group)
-  (define-key gnus-browse-mode-map "l" 'gnus-browse-exit)
-  (define-key gnus-browse-mode-map "L" 'gnus-browse-exit)
-  (define-key gnus-browse-mode-map "q" 'gnus-browse-exit)
-  (define-key gnus-browse-mode-map "Q" 'gnus-browse-exit)
-  (define-key gnus-browse-mode-map "\C-c\C-c" 'gnus-browse-exit)
-  (define-key gnus-browse-mode-map "?" 'gnus-browse-describe-briefly)
-  (define-key gnus-browse-mode-map "\C-c\C-i" 'gnus-info-find-node)
-  )
-
-(defvar gnus-browse-current-method nil)
-(defvar gnus-browse-return-buffer nil)
-
-(defvar gnus-browse-buffer "*Gnus Browse Server*")
-
-(defun gnus-browse-foreign-server (method &optional return-buffer)
-  "Browse the server METHOD."
-  (setq gnus-browse-current-method method)
-  (setq gnus-browse-return-buffer return-buffer)
-  (let ((gnus-select-method method)
-       groups group)
-    (gnus-message 5 "Connecting to %s..." (nth 1 method))
-    (cond 
-     ((not (gnus-check-server method))
-      (gnus-message 
-       1 "Unable to contact server: %s" (gnus-status-message method))
-      nil)
-     ((not (gnus-request-list method))
-      (gnus-message 
-       1 "Couldn't request list: %s" (gnus-status-message method))
-      nil)
-     (t
-      (get-buffer-create gnus-browse-buffer)
-      (gnus-add-current-to-buffer-list)
-      (and gnus-carpal (gnus-carpal-setup-buffer 'browse))
-      (gnus-configure-windows 'browse)
-      (buffer-disable-undo (current-buffer))
-      (let ((buffer-read-only nil))
-       (erase-buffer))
-      (gnus-browse-mode)
-      (setq mode-line-buffer-identification
-           (list
-            (format
-             "Gnus: %%b {%s:%s}" (car method) (car (cdr method)))))
-      (save-excursion
-       (set-buffer nntp-server-buffer)
-       (let ((cur (current-buffer)))
-         (goto-char (point-min))
-         (or (string= gnus-ignored-newsgroups "")
-             (delete-matching-lines gnus-ignored-newsgroups))
-         (while (re-search-forward 
-                 "\\(^[^ \t]+\\)[ \t]+[0-9]+[ \t]+[0-9]+" nil t)
-           (goto-char (match-end 1))
-           (setq groups (cons (cons (match-string 1)
-                                    (max 0 (- (1+ (read cur)) (read cur))))
-                              groups)))))
-      (setq groups (sort groups 
-                        (lambda (l1 l2)
-                          (string< (car l1) (car l2)))))
-      (let ((buffer-read-only nil))
-       (while groups
-         (setq group (car groups))
-         (insert 
-          (format "K%7d: %s\n" (cdr group) (car group)))
-         (setq groups (cdr groups))))
-      (switch-to-buffer (current-buffer))
-      (goto-char (point-min))
-      (gnus-group-position-point)
-      t))))
-
-(defun gnus-browse-mode ()
-  "Major mode for browsing a foreign server.
-
-All normal editing commands are switched off.
-
-\\<gnus-browse-mode-map>
-The only things you can do in this buffer is
-
-1) `\\[gnus-browse-unsubscribe-current-group]' to subscribe to a group.
-The group will be inserted into the group buffer upon exit from this
-buffer.  
-
-2) `\\[gnus-browse-read-group]' to read a group ephemerally.
-
-3) `\\[gnus-browse-exit]' to return to the group buffer."
-  (interactive)
-  (kill-all-local-variables)
-  (when (and menu-bar-mode
-            (gnus-visual-p 'browse-menu 'menu))
-    (gnus-browse-make-menu-bar))
-  (gnus-simplify-mode-line)
-  (setq major-mode 'gnus-browse-mode)
-  (setq mode-name "Browse Server")
-  (setq mode-line-process nil)
-  (use-local-map gnus-browse-mode-map)
-  (buffer-disable-undo (current-buffer))
-  (setq truncate-lines t)
-  (setq buffer-read-only t)
-  (run-hooks 'gnus-browse-mode-hook))
-
-(defun gnus-browse-read-group (&optional no-article)
-  "Enter the group at the current line."
-  (interactive)
-  (let ((group (gnus-browse-group-name)))
-    (or (gnus-group-read-ephemeral-group 
-        group gnus-browse-current-method nil
-        (cons (current-buffer) 'browse))
-       (error "Couldn't enter %s" group))))
-
-(defun gnus-browse-select-group ()
-  "Select the current group."
-  (interactive)
-  (gnus-browse-read-group 'no))
-
-(defun gnus-browse-next-group (n)
-  "Go to the next group."
-  (interactive "p")
-  (prog1
-      (forward-line n)
-    (gnus-group-position-point)))
-
-(defun gnus-browse-prev-group (n)
-  "Go to the next group."
-  (interactive "p")
-  (gnus-browse-next-group (- n)))
-
-(defun gnus-browse-unsubscribe-current-group (arg)
-  "(Un)subscribe to the next ARG groups."
-  (interactive "p")
-  (and (eobp)
-       (error "No group at current line."))
-  (let ((ward (if (< arg 0) -1 1))
-       (arg (abs arg)))
-    (while (and (> arg 0)
-               (not (eobp))
-               (gnus-browse-unsubscribe-group)
-               (zerop (gnus-browse-next-group ward)))
- &n