*** empty log message ***
[gnus] / lisp / gnus.el
index cb75aa5..2d0e98e 100644 (file)
@@ -18,8 +18,9 @@
 ;; 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.
 
@@ -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.
@@ -139,12 +135,19 @@ There is a lot more to know about select methods and virtual servers -
 see the manual for details.")
 
 (defvar gnus-message-archive-method 
-  '(nnfolder "archive" (nnfolder-directory "~/Mail/archive/")
-            (nnfolder-active-file "~/Mail/archive/active")
-            (nnfolder-get-new-mail nil)
-            (nnfolder-inhibit-expiry t))
+  `(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.")
+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.
@@ -153,7 +156,7 @@ 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.
@@ -186,15 +189,15 @@ 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,12 +215,13 @@ 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
+                 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/news.answers
+                 hwarang.postech.ac.kr          /pub/usenet
                  ftp.hk.super.net               /mirror/faqs")
 
 (defvar gnus-group-archive-directory
@@ -279,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.
+
+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-article-save-directory (or (getenv "SAVEDIR") "~/News/")
-  "*Name of the directory articles will be saved in (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 (or (getenv "SAVEDIR") "~/News/")
-  "*Name of the directory where kill files will be stored (default \"~/News\").
-Initialized from the SAVEDIR environment variable.")
+(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.
@@ -360,7 +366,7 @@ It uses the same syntax as the `gnus-split-methods' variable.")
 (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
@@ -369,6 +375,9 @@ 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
@@ -606,9 +615,6 @@ 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.")
 
@@ -760,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.")
 
@@ -794,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.
@@ -835,9 +851,9 @@ beginning of a line.")
                         (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))
+              (vertical ((height . 5) (width . 15)
+                         (user-position . t)
+                         (left . -1) (top . 1))
                         (picons 1.0))))
       (gnus-use-trees
        '(vertical 1.0
@@ -858,16 +874,9 @@ beginning of a line.")
      (vertical 1.0
               (browse 1.0 point)
               (if gnus-carpal '(browse-carpal 2))))
-    (group-mail
+    (message
      (vertical 1.0
-              (mail 1.0 point)))
-    (summary-mail
-     (vertical 1.0
-              (mail 1.0 point)))
-    (summary-reply
-     (vertical 1.0
-              (article 0.5)
-              (mail 1.0 point)))
+              (message 1.0 point)))
     (pick
      (vertical 1.0
               (article 1.0 point)))
@@ -895,21 +904,18 @@ 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)))
@@ -918,13 +924,14 @@ beginning of a line.")
               (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
@@ -953,12 +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)
     (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.")
 
@@ -972,7 +981,8 @@ 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>.
@@ -1073,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.
@@ -1096,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
@@ -1153,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
@@ -1208,28 +1220,30 @@ 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)
+    ("nnspool" post address)
     ("nnvirtual" post-mail virtual prompt-address)
-    ("nnmbox" mail respool)
-    ("nnml" mail respool)
-    ("nnmh" mail respool)
+    ("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)
+    ("nneething" none address prompt-address)
+    ("nndoc" none address prompt-address)
+    ("nnbabyl" mail address respool)
     ("nnkiboze" post virtual)
-    ("nnsoup" post-mail)
-    ("nnfolder" mail respool))
+    ("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
@@ -1256,7 +1270,7 @@ 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.")
@@ -1331,8 +1345,9 @@ course.)")
   "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.
 
@@ -1357,6 +1372,9 @@ It calls `gnus-summary-expire-articles' by default.")
 (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.")
 
@@ -1370,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;
@@ -1409,12 +1430,6 @@ If you want to run a special decoding program like nkf, use this hook.")
 ;(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.")
 
@@ -1464,6 +1479,7 @@ is not run if `gnus-visual' is 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.")
@@ -1474,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.")
 
@@ -1502,7 +1521,7 @@ The default function `gnus-group-highlight-line' will
 highlight the line according to the `gnus-group-highlight'
 variable.")
 
-(defvar gnus-mark-article-hook (list 'gnus-summary-mark-unread-as-read)
+(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.")
@@ -1517,16 +1536,40 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
            (remove-hook 'gnus-summary-prepare-hook
                         'hilit-rehighlight-buffer-quietly)
            (remove-hook 'gnus-summary-prepare-hook 'hilit-install-line-hooks)
-           (setq gnus-mark-article-hook '(gnus-summary-mark-unread-as-read))
+           (setq gnus-mark-article-hook
+                 '(gnus-summary-mark-read-and-unread-as-read))
            (remove-hook 'gnus-article-prepare-hook
                         'hilit-rehighlight-buffer-quietly)))
 
-
 \f
 ;; Internal variables
 
+(defvar gnus-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
@@ -1537,7 +1580,8 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
     (expirable . expire) (killed . killed)
     (bookmarks . bookmark) (dormant . dormant)
     (scored . score) (saved . save)
-    (cached . cache)))
+    (cached . cache)
+    ))
 
 ;; Avoid highlighting in kill files.
 (defvar gnus-summary-inhibit-highlight nil)
@@ -1546,6 +1590,7 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
 (defvar gnus-inhibit-hiding nil)
 (defvar gnus-group-indentation "")
 (defvar gnus-inhibit-limiting nil)
+(defvar gnus-created-frames nil)
 
 (defvar gnus-article-mode-map nil)
 (defvar gnus-dribble-buffer nil)
@@ -1554,8 +1599,6 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
 (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)
@@ -1563,6 +1606,8 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
 (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)
@@ -1604,6 +1649,7 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
     (?s gnus-tmp-news-server ?s)
     (?n gnus-tmp-news-method ?s)
     (?P gnus-group-indentation ?s)
+    (?l gnus-tmp-grouplens ?s)
     (?z gnus-tmp-news-method-string ?s)
     (?u gnus-tmp-user-defined ?s)))
 
@@ -1633,6 +1679,7 @@ It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
     (?\< (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
@@ -1647,34 +1694,35 @@ and what variables they correspond with, along with the type of the
 variable (string, integer, character, etc).")
 
 (defvar gnus-summary-dummy-line-format-alist
-  (` ((?S gnus-tmp-subject ?s)
-      (?N gnus-tmp-number ?d)
-      (?u gnus-tmp-user-defined ?s))))
+  `((?S gnus-tmp-subject ?s)
+    (?N gnus-tmp-number ?d)
+    (?u gnus-tmp-user-defined ?s)))
 
 (defvar gnus-summary-mode-line-format-alist
-  (` ((?G gnus-tmp-group-name ?s)
-      (?g (gnus-short-group-name gnus-tmp-group-name) ?s)
-      (?p (gnus-group-real-name gnus-tmp-group-name) ?s)
-      (?A gnus-tmp-article-number ?d)
-      (?Z gnus-tmp-unread-and-unselected ?s)
-      (?V gnus-version ?s)
-      (?U gnus-tmp-unread ?d)
-      (?S gnus-tmp-subject ?s)
-      (?e gnus-tmp-unselected ?d)
-      (?u gnus-tmp-user-defined ?s)
-      (?d (length gnus-newsgroup-dormant) ?d)
-      (?t (length gnus-newsgroup-marked) ?d)
-      (?r (length gnus-newsgroup-reads) ?d)
-      (?E gnus-newsgroup-expunged-tally ?d)
-      (?s (gnus-current-score-file-nondirectory) ?s))))
+  `((?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)
 
 (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))))
+  `((?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)
 
@@ -1682,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.36"
+(defconst gnus-version-number "5.2.25"
   "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*")
@@ -1704,9 +1759,6 @@ 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.")
 
@@ -1891,15 +1943,16 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
     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-newsgroup-async gnus-thread-expunge-below
     gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
-    gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files
+    (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.")
@@ -1953,16 +2006,14 @@ 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-soup-send-replies gnus-soup-save-areas gnus-soup-pack-packet)
      ("nnsoup" nnsoup-pack-replies)
+     ("gnus-scomo" :interactive t gnus-score-mode)
      ("gnus-mh" gnus-mh-mail-setup gnus-summary-save-article-folder
       gnus-Folder-save-name gnus-folder-save-name)
      ("gnus-mh" :interactive t gnus-summary-save-in-folder)
@@ -1986,12 +2037,14 @@ Thank you for your help in stamping out bugs.
       gnus-demon-init gnus-demon-cancel)
      ("gnus-salt" gnus-highlight-selected-tree gnus-possibly-generate-tree
       gnus-tree-open gnus-tree-close)
-     ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close)
+     ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
+      gnus-nocem-unwanted-article-p)
      ("gnus-srvr" gnus-enter-server-buffer gnus-server-set-info)
      ("gnus-srvr" gnus-browse-foreign-server)
      ("gnus-cite" :interactive t
       gnus-article-highlight-citation gnus-article-hide-citation-maybe
-      gnus-article-hide-citation gnus-article-fill-cited-article)
+      gnus-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)
@@ -1999,7 +2052,7 @@ Thank you for your help in stamping out bugs.
       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
@@ -2009,7 +2062,8 @@ Thank you for your help in stamping out bugs.
       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-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
@@ -2017,7 +2071,7 @@ Thank you for your help in stamping out bugs.
      ("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-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
@@ -2032,23 +2086,23 @@ Thank you for your help in stamping out bugs.
       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" :interactive t gnus-article-display-picons
-      gnus-group-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
 
@@ -2065,12 +2119,23 @@ Thank you for your help in stamping out bugs.
 
 (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."
@@ -2123,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))
@@ -2152,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))
@@ -2232,13 +2320,42 @@ 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)))))
+
+;; 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.
 
 (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
@@ -2278,7 +2395,7 @@ Thank you for your help in stamping out bugs.
 (defun gnus-summary-line-format-spec ()
   (insert gnus-tmp-unread gnus-tmp-replied
          gnus-tmp-score-char gnus-tmp-indentation)
-  (put-text-property
+  (gnus-put-text-property
    (point)
    (progn
      (insert
@@ -2298,7 +2415,7 @@ Thank you for your help in stamping out bugs.
 
 (defun gnus-summary-dummy-line-format-spec ()
   (insert "*  ")
-  (put-text-property
+  (gnus-put-text-property
    (point)
    (progn
      (insert ":                                 :")
@@ -2314,7 +2431,7 @@ Thank you for your help in stamping out bugs.
          gnus-tmp-process-marked
          gnus-group-indentation
          (format "%5s: " gnus-tmp-number-of-unread))
-  (put-text-property
+  (gnus-put-text-property
    (point)
    (progn
      (insert gnus-tmp-group "\n")
@@ -2376,9 +2493,10 @@ 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))
+      (let ((case-fold-search t)
+           (inhibit-point-motion-hooks t))
        (nnheader-narrow-to-headers)
-       (mail-fetch-field field)))))
+       (message-fetch-field field)))))
 
 (defun gnus-goto-colon ()
   (beginning-of-line)
@@ -2415,30 +2533,41 @@ Thank you for your help in stamping out bugs.
     (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))
 
+  ;; Go through all the formats and see whether they need updating.
   (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))))
+                        summary-mode group-mode article-mode))
+       new-format entry type val)
+    (while (setq type (pop types))
+      ;; Jump to the proper buffer to find out the value of
+      ;; the variable, if possible.  (It may be buffer-local.)
+      (save-excursion
+       (let ((buffer (intern (format "gnus-%s-buffer" type)))
+             val)
+         (when (and (boundp buffer)
+                    (setq val (symbol-value buffer))
+                    (get-buffer val)
+                    (buffer-name (get-buffer val)))
+           (set-buffer (get-buffer val)))
+         (setq new-format (symbol-value
+                           (intern (format "gnus-%s-line-format" type))))))
       (setq entry (cdr (assq type gnus-format-specs)))
       (if (and entry
               (equal (car entry) new-format))
+         ;; Use the old format.
          (set (intern (format "gnus-%s-line-format-spec" type))
-              (car (cdr entry)))
+              (cadr entry))
+       ;; This is a new format.
        (setq val
              (if (not (stringp new-format))
                  ;; This is a function call or something.
@@ -2451,45 +2580,56 @@ Thank you for your help in stamping out bugs.
                                  (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)
+       ;; Enter the new format spec into the list.
        (if entry
-           (setcar (cdr entry) val)
-         (push (list type new-format val) gnus-format-specs)))))
+           (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))))
 
-  (gnus-update-group-mark-positions)
-  (gnus-update-summary-mark-positions)
+  (unless (assq 'version gnus-format-specs)
+    (push (cons 'version emacs-version) gnus-format-specs))
 
-  (if (and (string-match "%[-,0-9]*D" gnus-group-line-format)
-          (not gnus-description-hashtb)
-          gnus-read-active-file)
-      (gnus-read-all-descriptions-files)))
+  (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)
@@ -2505,7 +2645,7 @@ 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
     ,(if (equal type 0)
@@ -2519,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)))))
 
@@ -2577,10 +2717,8 @@ 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)))
 
@@ -2622,16 +2760,16 @@ Thank you for your help in stamping out bugs.
            (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)
+                     ((= (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))))))
+             (setq newspec (cadr elem)))))
        ;; Remove the old specification (and possibly a ",12" string).
        (delete-region beg (match-end 2))
        ;; Insert the new specification.
@@ -2692,7 +2830,7 @@ Thank you for your help in stamping out bugs.
 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)
@@ -2726,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))
@@ -2744,7 +2882,7 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                       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))
@@ -2761,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.
@@ -2772,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
 
@@ -2790,12 +2928,15 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                 (cdr groups)
                 (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): "
                       (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
@@ -2821,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))
@@ -2846,8 +2989,8 @@ If variable `gnus-use-long-file-name' is non-nil, it is
   (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)))
 
@@ -2975,37 +3118,41 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
 ;; all whitespace.
 ;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
 (defun gnus-simplify-buffer-fuzzy ()
-  (goto-char (point-min))
-  (re-search-forward "^[ \t]*\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;][ \t]*" nil t)
-  (goto-char (match-beginning 0))
-  (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
@@ -3014,7 +3161,7 @@ If RE-ONLY is non-nil, strip leading `Re:'s 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."
@@ -3034,6 +3181,10 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
   (not (or (string< s1 s2)
           (string= s1 s2))))
 
+(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.
 
 (defun gnus-clear-system ()
@@ -3054,47 +3205,51 @@ If RE-ONLY is non-nil, strip leading `Re:'s 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)))))
@@ -3103,7 +3258,7 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
                        (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))
@@ -3114,14 +3269,17 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
        (or (not (numberp (nth i elem)))
            (zerop (nth i elem))
            (progn
-             (setq perc  (/ (float (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)
   "Add the window configuration CONF to `gnus-buffer-configuration'."
   (setq gnus-buffer-configuration
@@ -3189,7 +3347,8 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
            (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)))))
+           (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)
@@ -3252,19 +3411,22 @@ If RE-ONLY is non-nil, strip leading `Re:'s 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.
@@ -3274,10 +3436,22 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
       (let ((frame (selected-frame)))
        (unwind-protect
            (if gnus-use-full-window
-               (mapcar (lambda (frame)
-                         (select-frame frame)
-                         (delete-other-windows)) 
-                       (frame-list))
+               ;; 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)))
@@ -3286,45 +3460,51 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
       (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) (eq type 'frame)))
-      (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 t)))
-       (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)))))
+       (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)))
@@ -3335,7 +3515,7 @@ If RE-ONLY is non-nil, strip leading `Re:'s 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
@@ -3350,19 +3530,18 @@ If RE-ONLY is non-nil, strip leading `Re:'s 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))))))))))
+      (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)
@@ -3372,9 +3551,10 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
             (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)
@@ -3383,12 +3563,14 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
     ;; currently in use will have their message numbers taken into
     ;; 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."
@@ -3396,7 +3578,7 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
   ;; Enlarge info window if needed.
   (let ((mode major-mode)
        gnus-info-buffer)
-    (Info-goto-node (car (cdr (assq mode gnus-info-nodes))))
+    (Info-goto-node (cadr (assq mode gnus-info-nodes)))
     (setq gnus-info-buffer (current-buffer))
     (gnus-configure-windows 'info)))
 
@@ -3430,15 +3612,29 @@ If RE-ONLY is non-nil, strip leading `Re:'s 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))
@@ -3478,6 +3674,12 @@ that that variable is buffer-local to the summary buffers."
   (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
@@ -3505,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)
@@ -3538,14 +3749,30 @@ simple-first is t, first argument is already simplified."
 ;; 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.
@@ -3573,10 +3800,16 @@ simple-first is t, first argument is already simplified."
     ;; 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)
@@ -3586,20 +3819,41 @@ 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."
   (when (and references
-            (string-match "\\(<[^<>]+>\\)[ \t\n]*\\'" references))
+            (string-match "\\(<[^\n<>]+>\\)[ \t\n]*\\'" references))
     (substring references (match-beginning 1) (match-end 1))))
 
 (defun gnus-split-references (references)
@@ -3611,13 +3865,19 @@ simple-first is t, first argument is already simplified."
            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."
@@ -3761,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))))
@@ -3782,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
@@ -3792,7 +4052,7 @@ 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)))
@@ -3805,27 +4065,27 @@ Note: LIST has to be sorted over `<'."
       (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))))
+                                              (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)))
 
@@ -3845,12 +4105,12 @@ Note: LIST has to be sorted over `<'."
       (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))))
@@ -3880,147 +4140,139 @@ Note: LIST has to be sorted over `<'."
   (setq gnus-group-mode-map (make-keymap))
   (suppress-keymap gnus-group-mode-map)
 
-  (gnus-define-keys
-   gnus-group-mode-map
-   " " gnus-group-read-group
-   "=" gnus-group-select-group
-   "\M- " gnus-group-unhidden-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
-   "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)
-
-   (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))
+  (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.
@@ -4053,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")
@@ -4067,9 +4324,12 @@ The following commands are available:
 (defun gnus-group-default-level (&optional level number-or-nil)
   (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
@@ -4090,9 +4350,10 @@ 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)
@@ -4154,11 +4415,17 @@ prompt the user for the name of an NNTP server to use."
                (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)
@@ -4249,7 +4516,7 @@ 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
@@ -4284,6 +4551,7 @@ listed."
   (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)
@@ -4308,7 +4576,7 @@ listed."
                                  (text-property-any
                                   (point-min) (point-max) 'gnus-group
                                   (gnus-intern-safe
-                                   (car (car newsrc)) gnus-active-hashtb)))))
+                                   (caar newsrc) gnus-active-hashtb)))))
                  (setq newsrc (cdr newsrc)))
                (or newsrc (progn (goto-char (point-max))
                                  (forward-line -1)))))))
@@ -4346,9 +4614,9 @@ If REGEXP, only list groups matching REGEXP."
               (<= (setq clevel (gnus-info-level info)) level)
               (>= clevel lowest)
               (or all                  ; We list all groups?
-                  (and gnus-group-list-inactive-groups
-                       (eq unread t))  ; We list unactivated groups
-                  (> unread 0)         ; We list groups with unread articles
+                  (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
@@ -4381,14 +4649,14 @@ If REGEXP, only list groups matching REGEXP."
   ;; 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.
        (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)
@@ -4396,7 +4664,7 @@ 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 "     *: "
                           (setq group (pop groups)) "\n"))
@@ -4424,17 +4692,35 @@ If REGEXP, only list groups matching REGEXP."
   ;; 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))))
-
-(defmacro gnus-server-equal (ss1 ss2)
+  (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))
@@ -4445,12 +4731,35 @@ If REGEXP, only list groups matching REGEXP."
                  (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))
+              (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))
@@ -4461,15 +4770,29 @@ 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."
@@ -4516,11 +4839,26 @@ If SYMBOL, return the value of that symbol in the group parameters."
       (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.
 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.
@@ -4533,7 +4871,8 @@ 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))
@@ -4551,14 +4890,21 @@ 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
@@ -4572,9 +4918,7 @@ increase the score of each group you read."
          (setcar (nthcdr 2 entry) info)
          (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)
@@ -4587,17 +4931,19 @@ 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))
-        (gnus-group-indentation (gnus-group-group-indentation))
-        (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."
@@ -4619,9 +4965,9 @@ increase the score of each group you read."
           (- (1+ (cdr active)) (car active)) 0)
        nil))))
 
-(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
@@ -4651,12 +4997,12 @@ increase the score of each group you read."
          (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
          (if gnus-tmp-method
              (format "(%s:%s)" (car gnus-tmp-method)
-                     (car (cdr gnus-tmp-method))) ""))
+                     (cadr gnus-tmp-method)) ""))
         (gnus-tmp-marked-mark
          (if (and (numberp number)
                   (zerop number)
@@ -4665,10 +5011,14 @@ increase the score of each group you read."
         (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 gnus-tmp-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.
@@ -4680,7 +5030,7 @@ increase the score of each group you read."
        gnus-marked ,gnus-tmp-marked-mark
        gnus-indentation ,gnus-group-indentation
        gnus-level ,gnus-tmp-level))
-    (when (gnus-visual-p 'group-highlight 'highlight)
+    (when (inline (gnus-visual-p 'group-highlight 'highlight))
       (forward-line -1)
       (run-hooks 'gnus-group-update-hook)
       (forward-line))
@@ -4698,7 +5048,7 @@ 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)))
@@ -4713,48 +5063,70 @@ already."
          (goto-char loc)
          (let ((gnus-group-indentation (gnus-group-group-indentation)))
            (gnus-delete-line)
-           (gnus-group-insert-group-line-info group))
+           (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.
          (let ((gnus-group-indentation (gnus-group-group-indentation)))
-           (gnus-group-insert-group-line-info group)))
+           (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)
-          gnus-tmp-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."
@@ -4767,7 +5139,10 @@ already."
 
 (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) ""))
+  (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."
@@ -4824,24 +5199,23 @@ 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))
 
@@ -4853,6 +5227,7 @@ If FIRST-TOO, the current line is also eligible as a target."
 
 (defun gnus-group-unmark-all-groups ()
   "Unmark all groups."
+  (interactive)
   (let ((groups gnus-group-marked))
     (save-excursion
       (while groups
@@ -4897,11 +5272,10 @@ Return nil if the group isn't displayed."
 
 (defun gnus-group-set-mark (group)
   "Set the process mark on GROUP."
-  (if (gnus-group-goto-group 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)))))
+    (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."
@@ -4914,9 +5288,7 @@ Return nil if the group isn't displayed."
                             (substitute-command-keys
                              "\\<gnus-group-mode-map>\\[gnus-group-universal-argument]")))))
            'undefined)
-       (progn
-         (message "Undefined key")
-         (ding))
+       (gnus-error 1 "Undefined key")
       (while groups
        (gnus-group-remove-mark (setq group (pop groups)))
        (command-execute func))))
@@ -4942,6 +5314,7 @@ Take into consideration N (the prefix) and the list of marked groups."
       (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)))
@@ -5022,7 +5395,7 @@ 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.
@@ -5032,12 +5405,9 @@ Returns whether the fetching was successful or not."
                 (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)
@@ -5054,29 +5424,35 @@ Returns whether the fetching was successful or not."
   (interactive
    (list (completing-read
          "Group: " gnus-active-hashtb nil
-         (memq gnus-select-method gnus-have-read-active-file))))
+         (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)
            '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."
@@ -5152,10 +5528,12 @@ 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
@@ -5197,47 +5575,59 @@ ADDRESS."
     (let ((method
           (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)
+           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)
 
-      (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)))
+    ;; 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."
+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))
@@ -5252,12 +5642,11 @@ of the Earth\".  There is no undo."
          () ; 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)))
 
@@ -5287,15 +5676,12 @@ of the Earth\".  There is no undo."
   (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-set-active new-name (gnus-active group))
@@ -5303,17 +5689,16 @@ of the Earth\".  There is no undo."
        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"))
@@ -5326,9 +5711,6 @@ 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
@@ -5363,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)))
 
@@ -5405,10 +5801,10 @@ of the Earth\".  There is no undo."
                                    "etc/gnus-tut.txt"))))
        (setq path nil)))
     (if (not file)
-       (message "Couldn't find doc group")
+       (gnus-message 1 "Couldn't find doc group")
       (gnus-group-make-group
        (gnus-group-real-name name)
-       (list 'nndoc name
+       (list 'nndoc "gnus-help"
             (list 'nndoc-address file)
             (list 'nndoc-article-type 'mbox)))))
   (gnus-group-position-point))
@@ -5439,11 +5835,9 @@ of the Earth\".   There is no undo."
                 (file-name-nondirectory file) '(nndoc "")))))
     (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.
@@ -5458,9 +5852,7 @@ Given a prefix, create a full 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))
+                  gnus-group-recent-archive-directory))))))
 
 (defun gnus-group-make-directory-group (dir)
   "Create an nndir group.
@@ -5483,9 +5875,7 @@ mail messages or news articles in files that have numeric names."
       (setq ext (format "<%d>" (setq i (1+ i)))))
     (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.
@@ -5510,14 +5900,9 @@ score file entries for articles to include in the group."
        (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."
@@ -5664,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
@@ -5676,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
@@ -5692,11 +6094,13 @@ caught up is returned."
              (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)))
@@ -5753,20 +6157,23 @@ or nil if no action could be taken."
                            (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)))))
+           (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."
   (interactive)
@@ -5785,17 +6192,18 @@ or nil if no action could be taken."
     current-prefix-arg
     (string-to-int
      (let ((s (read-string
-              (format "Level (default %s): " (gnus-group-group-level)))))
+              (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 (or (gnus-group-group-level) gnus-level-killed)
@@ -5829,7 +6237,9 @@ group line."
   (interactive
    (list (completing-read
          "Group: " gnus-active-hashtb nil
-         (memq gnus-select-method gnus-have-read-active-file))))
+         (gnus-read-active-file-p)
+         nil 
+         'gnus-group-history)))
   (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb)))
     (cond
      ((string-match "^[ \t]$" group)
@@ -5844,7 +6254,7 @@ group line."
       (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
@@ -5918,11 +6328,10 @@ 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)))
+         (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
@@ -5930,12 +6339,21 @@ of groups killed."
       (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)
-         (when (setq entry (gnus-gethash (pop groups) gnus-newsrc-hashtb))
+         (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) (cdr (cdr (cdr entry))))))
+           (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)
@@ -5960,7 +6378,7 @@ is returned."
       ;; first newsgroup.
       (setq prev (gnus-group-group-name))
       (gnus-group-change-level
-       info (nth 2 info) gnus-level-killed
+       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))
@@ -6011,28 +6429,7 @@ 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)
@@ -6056,7 +6453,7 @@ entail asking the server for the groups."
   "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
+  (unless (gnus-read-active-file-p)
     (let ((gnus-read-active-file t))
       (gnus-read-active-file)))
   ;; Find all groups and sort them.
@@ -6065,7 +6462,8 @@ entail asking the server for the groups."
          (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)
@@ -6073,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)
@@ -6092,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))
@@ -6108,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)
@@ -6117,36 +6515,35 @@ 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)
-      (unless (gnus-get-new-news-in-group group)
-       (ding)
-       (gnus-message 3 "%s error: %s" group (gnus-status-message group))))
+      (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) t)
-    (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
    (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))))))
+                            (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)
@@ -6161,7 +6558,9 @@ If N is negative, this group and the N-1 previous groups will be checked."
 (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"))
@@ -6173,7 +6572,7 @@ If N is negative, this group and the N-1 previous groups will be checked."
                   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")))))
 
@@ -6193,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))))
@@ -6215,14 +6614,14 @@ If N is negative, this group and the N-1 previous groups will be checked."
            (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.
@@ -6258,8 +6657,14 @@ If N is negative, this group and the N-1 previous groups will be checked."
 If the prefix LEVEL is non-nil, it should be a number that says which
 level to cut off listing groups.
 If ALL, also list groups with no unread articles.
-If LOWEST, don't list groups with level lower than LOWEST."
+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))
@@ -6283,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."
@@ -6329,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."
@@ -6353,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-close))
-       ;; 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.
   (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)))))
@@ -6400,10 +6805,9 @@ 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-close))
-    (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."
@@ -6444,7 +6848,7 @@ and the second element is the address."
    (list (let ((how (completing-read
                     "Which backend: "
                     (append gnus-valid-select-methods gnus-server-alist)
-                    nil t (cons "nntp" 0))))
+                    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)
@@ -6473,296 +6877,284 @@ and the second element is the address."
 
   ;; Non-orthogonal keys
 
-  (gnus-define-keys
-   gnus-summary-mode-map
-   " " gnus-summary-next-page
-   "\177" gnus-summary-prev-page
-   "\r" gnus-summary-scroll-up
-   "n" gnus-summary-next-unread-article
-   "p" gnus-summary-prev-unread-article
-   "N" gnus-summary-next-article
-   "P" gnus-summary-prev-article
-   "\M-\C-n" gnus-summary-next-same-subject
-   "\M-\C-p" gnus-summary-prev-same-subject
-   "\M-n" gnus-summary-next-unread-subject
-   "\M-p" gnus-summary-prev-unread-subject
-   "." gnus-summary-first-unread-article
-   "," gnus-summary-best-unread-article
-   "\M-s" gnus-summary-search-article-forward
-   "\M-r" gnus-summary-search-article-backward
-   "<" gnus-summary-beginning-of-article
-   ">" gnus-summary-end-of-article
-   "j" gnus-summary-goto-article
-   "^" gnus-summary-refer-parent-article
-   "\M-^" gnus-summary-refer-article
-   "u" gnus-summary-tick-article-forward
-   "!" gnus-summary-tick-article-forward
-   "U" gnus-summary-tick-article-backward
-   "d" gnus-summary-mark-as-read-forward
-   "D" gnus-summary-mark-as-read-backward
-   "E" gnus-summary-mark-as-expirable
-   "\M-u" gnus-summary-clear-mark-forward
-   "\M-U" gnus-summary-clear-mark-backward
-   "k" gnus-summary-kill-same-subject-and-select
-   "\C-k" gnus-summary-kill-same-subject
-   "\M-\C-k" gnus-summary-kill-thread
-   "\M-\C-l" gnus-summary-lower-thread
-   "e" gnus-summary-edit-article
-   "#" gnus-summary-mark-as-processable
-   "\M-#" gnus-summary-unmark-as-processable
-   "\M-\C-t" gnus-summary-toggle-threads
-   "\M-\C-s" gnus-summary-show-thread
-   "\M-\C-h" gnus-summary-hide-thread
-   "\M-\C-f" gnus-summary-next-thread
-   "\M-\C-b" gnus-summary-prev-thread
-   "\M-\C-u" gnus-summary-up-thread
-   "\M-\C-d" gnus-summary-down-thread
-   "&" gnus-summary-execute-command
-   "c" gnus-summary-catchup-and-exit
-   "\C-w" gnus-summary-mark-region-as-read
-   "\C-t" gnus-summary-toggle-truncation
-   "?" gnus-summary-mark-as-dormant
-   "\C-c\M-\C-s" gnus-summary-limit-include-expunged
-   "\C-c\C-s\C-n" gnus-summary-sort-by-number
-   "\C-c\C-s\C-a" gnus-summary-sort-by-author
-   "\C-c\C-s\C-s" gnus-summary-sort-by-subject
-   "\C-c\C-s\C-d" gnus-summary-sort-by-date
-   "\C-c\C-s\C-i" gnus-summary-sort-by-score
-   "=" gnus-summary-expand-window
-   "\C-x\C-s" gnus-summary-reselect-current-group
-   "\M-g" gnus-summary-rescan-group
-   "w" gnus-summary-stop-page-breaking
-   "\C-c\C-r" gnus-summary-caesar-message
-   "\M-t" gnus-summary-toggle-mime
-   "f" gnus-summary-followup
-   "F" gnus-summary-followup-with-original
-   "C" gnus-summary-cancel-article
-   "r" gnus-summary-reply
-   "R" gnus-summary-reply-with-original
-   "\C-c\C-f" gnus-summary-mail-forward
-   "o" gnus-summary-save-article
-   "\C-o" gnus-summary-save-article-mail
-   "|" gnus-summary-pipe-output
-   "\M-k" gnus-summary-edit-local-kill
-   "\M-K" gnus-summary-edit-global-kill
-   "V" gnus-version
-   "\C-c\C-d" gnus-summary-describe-group
-   "q" gnus-summary-exit
-   "Q" gnus-summary-exit-no-update
-   "\C-c\C-i" gnus-info-find-node
-   gnus-mouse-2 gnus-mouse-pick-article
-   "m" gnus-summary-mail-other-window
-   "a" gnus-summary-post-news
-   "x" gnus-summary-limit-to-unread
-   "s" gnus-summary-isearch-article
-   "t" gnus-article-hide-headers
-   "g" gnus-summary-show-article
-   "l" gnus-summary-goto-last-article
-   "\C-c\C-v\C-v" gnus-uu-decode-uu-view
-   "\C-d" gnus-summary-enter-digest-group
-   "\C-c\C-b" gnus-bug
-   "*" gnus-cache-enter-article
-   "\M-*" gnus-cache-remove-article
-   "\M-&" gnus-summary-universal-argument
-   "\C-l" gnus-recenter
-   "I" gnus-summary-increase-score
-   "L" gnus-summary-lower-score
-
-   "V" gnus-summary-score-map
-   "X" gnus-uu-extract-map
-   "S" gnus-summary-send-map)
+  (gnus-define-keys gnus-summary-mode-map
+    " " gnus-summary-next-page
+    "\177" gnus-summary-prev-page
+    [delete] gnus-summary-prev-page
+    "\r" gnus-summary-scroll-up
+    "n" gnus-summary-next-unread-article
+    "p" gnus-summary-prev-unread-article
+    "N" gnus-summary-next-article
+    "P" gnus-summary-prev-article
+    "\M-\C-n" gnus-summary-next-same-subject
+    "\M-\C-p" gnus-summary-prev-same-subject
+    "\M-n" gnus-summary-next-unread-subject
+    "\M-p" gnus-summary-prev-unread-subject
+    "." gnus-summary-first-unread-article
+    "," gnus-summary-best-unread-article
+    "\M-s" gnus-summary-search-article-forward
+    "\M-r" gnus-summary-search-article-backward
+    "<" gnus-summary-beginning-of-article
+    ">" gnus-summary-end-of-article
+    "j" gnus-summary-goto-article
+    "^" gnus-summary-refer-parent-article
+    "\M-^" gnus-summary-refer-article
+    "u" gnus-summary-tick-article-forward
+    "!" gnus-summary-tick-article-forward
+    "U" gnus-summary-tick-article-backward
+    "d" gnus-summary-mark-as-read-forward
+    "D" gnus-summary-mark-as-read-backward
+    "E" gnus-summary-mark-as-expirable
+    "\M-u" gnus-summary-clear-mark-forward
+    "\M-U" gnus-summary-clear-mark-backward
+    "k" gnus-summary-kill-same-subject-and-select
+    "\C-k" gnus-summary-kill-same-subject
+    "\M-\C-k" gnus-summary-kill-thread
+    "\M-\C-l" gnus-summary-lower-thread
+    "e" gnus-summary-edit-article
+    "#" gnus-summary-mark-as-processable
+    "\M-#" gnus-summary-unmark-as-processable
+    "\M-\C-t" gnus-summary-toggle-threads
+    "\M-\C-s" gnus-summary-show-thread
+    "\M-\C-h" gnus-summary-hide-thread
+    "\M-\C-f" gnus-summary-next-thread
+    "\M-\C-b" gnus-summary-prev-thread
+    "\M-\C-u" gnus-summary-up-thread
+    "\M-\C-d" gnus-summary-down-thread
+    "&" gnus-summary-execute-command
+    "c" gnus-summary-catchup-and-exit
+    "\C-w" gnus-summary-mark-region-as-read
+    "\C-t" gnus-summary-toggle-truncation
+    "?" gnus-summary-mark-as-dormant
+    "\C-c\M-\C-s" gnus-summary-limit-include-expunged
+    "\C-c\C-s\C-n" gnus-summary-sort-by-number
+    "\C-c\C-s\C-a" gnus-summary-sort-by-author
+    "\C-c\C-s\C-s" gnus-summary-sort-by-subject
+    "\C-c\C-s\C-d" gnus-summary-sort-by-date
+    "\C-c\C-s\C-i" gnus-summary-sort-by-score
+    "=" gnus-summary-expand-window
+    "\C-x\C-s" gnus-summary-reselect-current-group
+    "\M-g" gnus-summary-rescan-group
+    "w" gnus-summary-stop-page-breaking
+    "\C-c\C-r" gnus-summary-caesar-message
+    "\M-t" gnus-summary-toggle-mime
+    "f" gnus-summary-followup
+    "F" gnus-summary-followup-with-original
+    "C" gnus-summary-cancel-article
+    "r" gnus-summary-reply
+    "R" gnus-summary-reply-with-original
+    "\C-c\C-f" gnus-summary-mail-forward
+    "o" gnus-summary-save-article
+    "\C-o" gnus-summary-save-article-mail
+    "|" gnus-summary-pipe-output
+    "\M-k" gnus-summary-edit-local-kill
+    "\M-K" gnus-summary-edit-global-kill
+    "V" gnus-version
+    "\C-c\C-d" gnus-summary-describe-group
+    "q" gnus-summary-exit
+    "Q" gnus-summary-exit-no-update
+    "\C-c\C-i" gnus-info-find-node
+    gnus-mouse-2 gnus-mouse-pick-article
+    "m" gnus-summary-mail-other-window
+    "a" gnus-summary-post-news
+    "x" gnus-summary-limit-to-unread
+    "s" gnus-summary-isearch-article
+    "t" gnus-article-hide-headers
+    "g" gnus-summary-show-article
+    "l" gnus-summary-goto-last-article
+    "\C-c\C-v\C-v" gnus-uu-decode-uu-view
+    "\C-d" gnus-summary-enter-digest-group
+    "\C-c\C-b" gnus-bug
+    "*" gnus-cache-enter-article
+    "\M-*" gnus-cache-remove-article
+    "\M-&" gnus-summary-universal-argument
+    "\C-l" gnus-recenter
+    "I" gnus-summary-increase-score
+    "L" gnus-summary-lower-score
+
+    "V" gnus-summary-score-map
+    "X" gnus-uu-extract-map
+    "S" gnus-summary-send-map)
 
   ;; Sort of orthogonal keymap
-  (gnus-define-keys
-   (gnus-summary-mark-map "M" gnus-summary-mode-map)
-   "t" gnus-summary-tick-article-forward
-   "!" gnus-summary-tick-article-forward
-   "d" gnus-summary-mark-as-read-forward
-   "r" gnus-summary-mark-as-read-forward
-   "c" gnus-summary-clear-mark-forward
-   " " gnus-summary-clear-mark-forward
-   "e" gnus-summary-mark-as-expirable
-   "x" gnus-summary-mark-as-expirable
-   "?" gnus-summary-mark-as-dormant
-   "b" gnus-summary-set-bookmark
-   "B" gnus-summary-remove-bookmark
-   "#" gnus-summary-mark-as-processable
-   "\M-#" gnus-summary-unmark-as-processable
-   "S" gnus-summary-limit-include-expunged
-   "C" gnus-summary-catchup
-   "H" gnus-summary-catchup-to-here
-   "\C-c" gnus-summary-catchup-all
-   "k" gnus-summary-kill-same-subject-and-select
-   "K" gnus-summary-kill-same-subject
-   "P" gnus-uu-mark-map)
-
-  (gnus-define-keys
-   (gnus-summary-mscore-map "V" gnus-summary-mode-map)
-   "c" gnus-summary-clear-above
-   "u" gnus-summary-tick-above
-   "m" gnus-summary-mark-above
-   "k" gnus-summary-kill-below)
-
-  (gnus-define-keys
-   (gnus-summary-limit-map "/" gnus-summary-mode-map)
-   "/" gnus-summary-limit-to-subject
-   "n" gnus-summary-limit-to-articles
-   "w" gnus-summary-pop-limit
-   "s" gnus-summary-limit-to-subject
-   "a" gnus-summary-limit-to-author
-   "u" gnus-summary-limit-to-unread
-   "m" gnus-summary-limit-to-marks
-   "v" gnus-summary-limit-to-score
-   "D" gnus-summary-limit-include-dormant
-   "d" gnus-summary-limit-exclude-dormant
-;;  "t" gnus-summary-limit-exclude-thread
-   "E" gnus-summary-limit-include-expunged
-   "c" gnus-summary-limit-exclude-childless-dormant
-   "C" gnus-summary-limit-mark-excluded-as-read)
-
-  (gnus-define-keys
-   (gnus-summary-goto-map "G" gnus-summary-mode-map)
-   "n" gnus-summary-next-unread-article
-   "p" gnus-summary-prev-unread-article
-   "N" gnus-summary-next-article
-   "P" gnus-summary-prev-article
-   "\C-n" gnus-summary-next-same-subject
-   "\C-p" gnus-summary-prev-same-subject
-   "\M-n" gnus-summary-next-unread-subject
-   "\M-p" gnus-summary-prev-unread-subject
-   "f" gnus-summary-first-unread-article
-   "b" gnus-summary-best-unread-article
-   "g" gnus-summary-goto-subject
-   "l" gnus-summary-goto-last-article
-   "p" gnus-summary-pop-article)
-
-  (gnus-define-keys
-   (gnus-summary-thread-map "T" gnus-summary-mode-map)
-   "k" gnus-summary-kill-thread
-   "l" gnus-summary-lower-thread
-   "i" gnus-summary-raise-thread
-   "T" gnus-summary-toggle-threads
-   "t" gnus-summary-rethread-current
-   "^" gnus-summary-reparent-thread
-   "s" gnus-summary-show-thread
-   "S" gnus-summary-show-all-threads
-   "h" gnus-summary-hide-thread
-   "H" gnus-summary-hide-all-threads
-   "n" gnus-summary-next-thread
-   "p" gnus-summary-prev-thread
-   "u" gnus-summary-up-thread
-   "o" gnus-summary-top-thread
-   "d" gnus-summary-down-thread
-   "#" gnus-uu-mark-thread
-   "\M-#" gnus-uu-unmark-thread)
-
-  (gnus-define-keys
-   (gnus-summary-exit-map "Z" gnus-summary-mode-map)
-   "c" gnus-summary-catchup-and-exit
-   "C" gnus-summary-catchup-all-and-exit
-   "E" gnus-summary-exit-no-update
-   "Q" gnus-summary-exit
-   "Z" gnus-summary-exit
-   "n" gnus-summary-catchup-and-goto-next-group
-   "R" gnus-summary-reselect-current-group
-   "G" gnus-summary-rescan-group
-   "N" gnus-summary-next-group
-   "P" gnus-summary-prev-group)
-
-  (gnus-define-keys
-   (gnus-summary-article-map "A" gnus-summary-mode-map)
-   " " gnus-summary-next-page
-   "n" gnus-summary-next-page
-   "\177" gnus-summary-prev-page
-   "p" gnus-summary-prev-page
-   "\r" gnus-summary-scroll-up
-   "<" gnus-summary-beginning-of-article
-   ">" gnus-summary-end-of-article
-   "b" gnus-summary-beginning-of-article
-   "e" gnus-summary-end-of-article
-   "^" gnus-summary-refer-parent-article
-   "r" gnus-summary-refer-parent-article
-   "R" gnus-summary-refer-references
-   "g" gnus-summary-show-article
-   "s" gnus-summary-isearch-article)
-
-  (gnus-define-keys
-   (gnus-summary-wash-map "W" gnus-summary-mode-map)
-   "b" gnus-article-add-buttons
-   "B" gnus-article-add-buttons-to-head
-   "o" gnus-article-treat-overstrike
-;;  "w" gnus-article-word-wrap
-   "w" gnus-article-fill-cited-article
-   "c" gnus-article-remove-cr
-   "L" gnus-article-remove-trailing-blank-lines
-   "q" gnus-article-de-quoted-unreadable
-   "f" gnus-article-display-x-face
-   "l" gnus-summary-stop-page-breaking
-   "r" gnus-summary-caesar-message
-   "t" gnus-summary-toggle-header
-   "v" gnus-summary-verbose-headers
-   "m" gnus-summary-toggle-mime)
-
-  (gnus-define-keys
-   (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
-   "a" gnus-article-hide
-   "h" gnus-article-hide-headers
-   "b" gnus-article-hide-boring-headers
-   "s" gnus-article-hide-signature
-   "c" gnus-article-hide-citation
-   "p" gnus-article-hide-pgp
-   "\C-c" gnus-article-hide-citation-maybe)
-
-  (gnus-define-keys
-   (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
-   "a" gnus-article-highlight
-   "h" gnus-article-highlight-headers
-   "c" gnus-article-highlight-citation
-   "s" gnus-article-highlight-signature)
-
-  (gnus-define-keys
-   (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
-   "z" gnus-article-date-ut
-   "u" gnus-article-date-ut
-   "l" gnus-article-date-local
-   "e" gnus-article-date-lapsed
-   "o" gnus-article-date-original)
-
-  (gnus-define-keys
-   (gnus-summary-help-map "H" gnus-summary-mode-map)
-   "v" gnus-version
-   "f" gnus-summary-fetch-faq
-   "d" gnus-summary-describe-group
-   "h" gnus-summary-describe-briefly
-   "i" gnus-info-find-node)
-
-  (gnus-define-keys
-   (gnus-summary-backend-map "B" gnus-summary-mode-map)
-   "e" gnus-summary-expire-articles
-   "\M-\C-e" gnus-summary-expire-articles-now
-   "\177" gnus-summary-delete-article
-   "m" gnus-summary-move-article
-   "r" gnus-summary-respool-article
-   "w" gnus-summary-edit-article
-   "c" gnus-summary-copy-article
-   "B" gnus-summary-crosspost-article
-   "q" gnus-summary-respool-query
-   "i" gnus-summary-import-article)
-
-  (gnus-define-keys
-   (gnus-summary-save-map "O" gnus-summary-mode-map)
-   "o" gnus-summary-save-article
-   "m" gnus-summary-save-article-mail
-   "r" gnus-summary-save-article-rmail
-   "f" gnus-summary-save-article-file
-   "b" gnus-summary-save-article-body-file
-   "h" gnus-summary-save-article-folder
-   "v" gnus-summary-save-article-vm
-   "p" gnus-summary-pipe-output
-   "s" gnus-soup-add-article)
+  (gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map)
+    "t" gnus-summary-tick-article-forward
+    "!" gnus-summary-tick-article-forward
+    "d" gnus-summary-mark-as-read-forward
+    "r" gnus-summary-mark-as-read-forward
+    "c" gnus-summary-clear-mark-forward
+    " " gnus-summary-clear-mark-forward
+    "e" gnus-summary-mark-as-expirable
+    "x" gnus-summary-mark-as-expirable
+    "?" gnus-summary-mark-as-dormant
+    "b" gnus-summary-set-bookmark
+    "B" gnus-summary-remove-bookmark
+    "#" gnus-summary-mark-as-processable
+    "\M-#" gnus-summary-unmark-as-processable
+    "S" gnus-summary-limit-include-expunged
+    "C" gnus-summary-catchup
+    "H" gnus-summary-catchup-to-here
+    "\C-c" gnus-summary-catchup-all
+    "k" gnus-summary-kill-same-subject-and-select
+    "K" gnus-summary-kill-same-subject
+    "P" gnus-uu-mark-map)
+
+  (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mode-map)
+    "c" gnus-summary-clear-above
+    "u" gnus-summary-tick-above
+    "m" gnus-summary-mark-above
+    "k" gnus-summary-kill-below)
+
+  (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
+    "/" gnus-summary-limit-to-subject
+    "n" gnus-summary-limit-to-articles
+    "w" gnus-summary-pop-limit
+    "s" gnus-summary-limit-to-subject
+    "a" gnus-summary-limit-to-author
+    "u" gnus-summary-limit-to-unread
+    "m" gnus-summary-limit-to-marks
+    "v" gnus-summary-limit-to-score
+    "D" gnus-summary-limit-include-dormant
+    "d" gnus-summary-limit-exclude-dormant
+    ;;  "t" gnus-summary-limit-exclude-thread
+    "E" gnus-summary-limit-include-expunged
+    "c" gnus-summary-limit-exclude-childless-dormant
+    "C" gnus-summary-limit-mark-excluded-as-read)
+
+  (gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
+    "n" gnus-summary-next-unread-article
+    "p" gnus-summary-prev-unread-article
+    "N" gnus-summary-next-article
+    "P" gnus-summary-prev-article
+    "\C-n" gnus-summary-next-same-subject
+    "\C-p" gnus-summary-prev-same-subject
+    "\M-n" gnus-summary-next-unread-subject
+    "\M-p" gnus-summary-prev-unread-subject
+    "f" gnus-summary-first-unread-article
+    "b" gnus-summary-best-unread-article
+    "j" gnus-summary-goto-article
+    "g" gnus-summary-goto-subject
+    "l" gnus-summary-goto-last-article
+    "p" gnus-summary-pop-article)
+
+  (gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
+    "k" gnus-summary-kill-thread
+    "l" gnus-summary-lower-thread
+    "i" gnus-summary-raise-thread
+    "T" gnus-summary-toggle-threads
+    "t" gnus-summary-rethread-current
+    "^" gnus-summary-reparent-thread
+    "s" gnus-summary-show-thread
+    "S" gnus-summary-show-all-threads
+    "h" gnus-summary-hide-thread
+    "H" gnus-summary-hide-all-threads
+    "n" gnus-summary-next-thread
+    "p" gnus-summary-prev-thread
+    "u" gnus-summary-up-thread
+    "o" gnus-summary-top-thread
+    "d" gnus-summary-down-thread
+    "#" gnus-uu-mark-thread
+    "\M-#" gnus-uu-unmark-thread)
+
+  (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
+    "c" gnus-summary-catchup-and-exit
+    "C" gnus-summary-catchup-all-and-exit
+    "E" gnus-summary-exit-no-update
+    "Q" gnus-summary-exit
+    "Z" gnus-summary-exit
+    "n" gnus-summary-catchup-and-goto-next-group
+    "R" gnus-summary-reselect-current-group
+    "G" gnus-summary-rescan-group
+    "N" gnus-summary-next-group
+    "P" gnus-summary-prev-group)
+
+  (gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
+    " " gnus-summary-next-page
+    "n" gnus-summary-next-page
+    "\177" gnus-summary-prev-page
+    [delete] gnus-summary-prev-page
+    "p" gnus-summary-prev-page
+    "\r" gnus-summary-scroll-up
+    "<" gnus-summary-beginning-of-article
+    ">" gnus-summary-end-of-article
+    "b" gnus-summary-beginning-of-article
+    "e" gnus-summary-end-of-article
+    "^" gnus-summary-refer-parent-article
+    "r" gnus-summary-refer-parent-article
+    "R" gnus-summary-refer-references
+    "g" gnus-summary-show-article
+    "s" gnus-summary-isearch-article)
+
+  (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
+    "b" gnus-article-add-buttons
+    "B" gnus-article-add-buttons-to-head
+    "o" gnus-article-treat-overstrike
+    ;;  "w" gnus-article-word-wrap
+    "w" gnus-article-fill-cited-article
+    "c" gnus-article-remove-cr
+    "L" gnus-article-remove-trailing-blank-lines
+    "q" gnus-article-de-quoted-unreadable
+    "f" gnus-article-display-x-face
+    "l" gnus-summary-stop-page-breaking
+    "r" gnus-summary-caesar-message
+    "t" gnus-article-hide-headers
+    "v" gnus-summary-verbose-headers
+    "m" gnus-summary-toggle-mime)
+
+  (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
+    "a" gnus-article-hide
+    "h" gnus-article-hide-headers
+    "b" gnus-article-hide-boring-headers
+    "s" gnus-article-hide-signature
+    "c" gnus-article-hide-citation
+    "p" gnus-article-hide-pgp
+    "\C-c" gnus-article-hide-citation-maybe)
+
+  (gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
+    "a" gnus-article-highlight
+    "h" gnus-article-highlight-headers
+    "c" gnus-article-highlight-citation
+    "s" gnus-article-highlight-signature)
+
+  (gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
+    "z" gnus-article-date-ut
+    "u" gnus-article-date-ut
+    "l" gnus-article-date-local
+    "e" gnus-article-date-lapsed
+    "o" gnus-article-date-original)
+
+  (gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
+    "v" gnus-version
+    "f" gnus-summary-fetch-faq
+    "d" gnus-summary-describe-group
+    "h" gnus-summary-describe-briefly
+    "i" gnus-info-find-node)
+
+  (gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
+    "e" gnus-summary-expire-articles
+    "\M-\C-e" gnus-summary-expire-articles-now
+    "\177" gnus-summary-delete-article
+    [delete] gnus-summary-delete-article
+    "m" gnus-summary-move-article
+    "r" gnus-summary-respool-article
+    "w" gnus-summary-edit-article
+    "c" gnus-summary-copy-article
+    "B" gnus-summary-crosspost-article
+    "q" gnus-summary-respool-query
+    "i" gnus-summary-import-article)
+
+  (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
+    "o" gnus-summary-save-article
+    "m" gnus-summary-save-article-mail
+    "r" gnus-summary-save-article-rmail
+    "f" gnus-summary-save-article-file
+    "b" gnus-summary-save-article-body-file
+    "h" gnus-summary-save-article-folder
+    "v" gnus-summary-save-article-vm
+    "p" gnus-summary-pipe-output
+    "s" gnus-soup-add-article)
   )
 
-
 \f
 
 (defun gnus-summary-mode (&optional group)
@@ -6790,15 +7182,7 @@ The following commands are available:
             (gnus-visual-p 'summary-menu 'menu))
     (gnus-summary-make-menu-bar))
   (kill-all-local-variables)
-  (let ((locals gnus-summary-local-variables))
-    (while locals
-      (if (consp (car locals))
-         (progn
-           (make-local-variable (car (car locals)))
-           (set (car (car locals)) (eval (cdr (car locals)))))
-       (make-local-variable (car locals))
-       (set (car locals) nil))
-      (setq locals (cdr locals))))
+  (gnus-summary-make-local-variables)
   (gnus-make-thread-indent-array)
   (gnus-simplify-mode-line)
   (setq major-mode 'gnus-summary-mode)
@@ -6812,8 +7196,29 @@ The following commands are available:
   (setq selective-display-ellipses t)  ;Display `...'
   (setq buffer-display-table gnus-summary-display-table)
   (setq gnus-newsgroup-name group)
+  (make-local-variable 'gnus-summary-line-format)
+  (make-local-variable 'gnus-summary-line-format-spec)
+  (make-local-variable 'gnus-summary-mark-positions)
   (run-hooks 'gnus-summary-mode-hook))
 
+(defun gnus-summary-make-local-variables ()
+  "Make all the local summary buffer variables."
+  (let ((locals gnus-summary-local-variables)
+       global local)
+    (while (setq local (pop locals))
+      (if (consp local)
+         (progn
+           (if (eq (cdr local) 'global)
+               ;; Copy the global value of the variable.
+               (setq global (symbol-value (car local)))
+             ;; Use the value from the list.
+             (setq global (eval (cdr local))))
+           (make-local-variable (car local))
+           (set (car local) global))
+       ;; Simple nil-valued local variable.
+       (make-local-variable local)
+       (set local nil)))))
+
 (defun gnus-summary-make-display-table ()
   ;; Change the display table. Odd characters have a tendency to mess
   ;; up nicely formatted displays - we make all possible glyphs
@@ -6842,8 +7247,8 @@ The following commands are available:
   (let ((locals gnus-summary-local-variables))
     (while locals
       (if (consp (car locals))
-         (and (vectorp (car (car locals)))
-              (set (car (car locals)) nil))
+         (and (vectorp (caar locals))
+              (set (caar locals) nil))
        (and (vectorp (car locals))
             (set (car locals) nil)))
       (setq locals (cdr locals)))))
@@ -6897,7 +7302,7 @@ The following commands are available:
     (setcdr data (cons (gnus-data-make number mark pos header level)
                       (cdr data)))
     (setq gnus-newsgroup-data-reverse nil)
-    (gnus-data-update-list (cdr (cdr data)) offset)))
+    (gnus-data-update-list (cddr data) offset)))
 
 (defun gnus-data-enter-list (after-article list &optional offset)
   (when list
@@ -6924,9 +7329,9 @@ The following commands are available:
        (setq gnus-newsgroup-data (cdr gnus-newsgroup-data)
              gnus-newsgroup-data-reverse nil)
       (while (cdr data)
-       (and (= (gnus-data-number (car (cdr data))) article)
+       (and (= (gnus-data-number (cadr data)) article)
             (progn
-              (setcdr data (cdr (cdr data)))
+              (setcdr data (cddr data))
               (and offset (gnus-data-update-list (cdr data) offset))
               (setq data nil
                     gnus-newsgroup-data-reverse nil)))
@@ -6962,16 +7367,27 @@ The following commands are available:
 
 (defun gnus-article-parent-p (number)
   "Say whether this article is a parent or not."
-  (let* ((data (gnus-data-find-list number)))
+  (let ((data (gnus-data-find-list number)))
     (and (cdr data)                    ; There has to be an article after...
         (< (gnus-data-level (car data)) ; And it has to have a higher level.
            (gnus-data-level (nth 1 data))))))
 
+(defun gnus-article-children (number)
+  "Return a list of all children to NUMBER."
+  (let* ((data (gnus-data-find-list number))
+        (level (gnus-data-level (car data)))
+        children)
+    (setq data (cdr data))
+    (while (and data           
+               (= (gnus-data-level (car data)) (1+ level)))
+      (push (gnus-data-number (car data)) children)
+      (setq data (cdr data)))
+    children))
+
 (defmacro gnus-summary-skip-intangible ()
   "If the current article is intangible, then jump to a different article."
   '(let ((to (get-text-property (point) 'gnus-intangible)))
-    (when to
-      (gnus-summary-goto-subject to))))
+    (and to (gnus-summary-goto-subject to))))
 
 (defmacro gnus-summary-article-intangible-p ()
   "Say whether this article is intangible or not."
@@ -7007,6 +7423,7 @@ article number."
   `(gnus-data-pos (gnus-data-find
                   ,(or number '(gnus-summary-article-number)))))
 
+(defalias 'gnus-summary-subject-string 'gnus-summary-article-subject)
 (defmacro gnus-summary-article-subject (&optional number)
   "Return current subject string or nil if nothing."
   `(let ((headers
@@ -7038,8 +7455,7 @@ article number."
 (defun gnus-summary-article-parent (&optional number)
   (let* ((data (gnus-data-find-list (or number (gnus-summary-article-number))
                                    (gnus-data-list t)))
-        (level (gnus-data-level (car data)))
-        l)
+        (level (gnus-data-level (car data))))
     (if (zerop level)
        () ; This is a root.
       ;; We search until we find an article with a level less than
@@ -7048,6 +7464,50 @@ article number."
                  (not (< (gnus-data-level (car data)) level))))
       (and data (gnus-data-number (car data))))))
 
+(defun gnus-unread-mark-p (mark)
+  "Say whether MARK is the unread mark."
+  (= mark gnus-unread-mark))
+
+(defun gnus-read-mark-p (mark)
+  "Say whether MARK is one of the marks that mark as read.
+This is all marks except unread, ticked, dormant, and expirable."
+  (not (or (= mark gnus-unread-mark)
+          (= mark gnus-ticked-mark)
+          (= mark gnus-dormant-mark)
+          (= mark gnus-expirable-mark))))
+
+;; Saving hidden threads.
+
+(put 'gnus-save-hidden-threads 'lisp-indent-function 0)
+(put 'gnus-save-hidden-threads 'lisp-indent-hook 0)
+(put 'gnus-save-hidden-threads 'edebug-form-spec '(body))
+
+(defmacro gnus-save-hidden-threads (&rest forms)
+  "Save hidden threads, eval FORMS, and restore the hidden threads."
+  (let ((config (make-symbol "config")))
+    `(let ((,config (gnus-hidden-threads-configuration)))
+       (unwind-protect
+          (progn
+            ,@forms)
+        (gnus-restore-hidden-threads-configuration ,config)))))
+
+(defun gnus-hidden-threads-configuration ()
+  "Return the current hidden threads configuration."
+  (save-excursion
+    (let (config)
+      (goto-char (point-min))
+      (while (search-forward "\r" nil t)
+       (push (1- (point)) config))
+      config)))
+
+(defun gnus-restore-hidden-threads-configuration (config)
+  "Restore hidden threads configuration from CONFIG."
+  (let (point buffer-read-only)
+    (while (setq point (pop config))
+      (when (and (< point (point-max))
+                (goto-char point)
+                (= (following-char) ?\n))
+       (subst-char-in-region point (1+ point) ?\n ?\r)))))
 
 ;; Various summary mode internalish functions.
 
@@ -7072,6 +7532,7 @@ article number."
        (gnus-carpal-setup-buffer 'summary))
       (unless gnus-single-article-buffer
        (make-local-variable 'gnus-article-buffer)
+       (make-local-variable 'gnus-article-current)
        (make-local-variable 'gnus-original-article-buffer))
       (setq gnus-newsgroup-name group)
       t)))
@@ -7087,7 +7548,10 @@ article number."
          (unread gnus-newsgroup-unreads)
          (headers gnus-current-headers)
          (data gnus-newsgroup-data)
+         (summary gnus-summary-buffer)
          (article-buffer gnus-article-buffer)
+         (original gnus-original-article-buffer)
+         (gac gnus-article-current)
          (score-file gnus-current-score-file))
       (save-excursion
        (set-buffer gnus-group-buffer)
@@ -7096,29 +7560,29 @@ article number."
        (setq gnus-newsgroup-unreads unread)
        (setq gnus-current-headers headers)
        (setq gnus-newsgroup-data data)
+       (setq gnus-article-current gac)
+       (setq gnus-summary-buffer summary)
        (setq gnus-article-buffer article-buffer)
+       (setq gnus-original-article-buffer original)
        (setq gnus-current-score-file score-file)))))
 
 (defun gnus-summary-last-article-p (&optional article)
   "Return whether ARTICLE is the last article in the buffer."
   (if (not (setq article (or article (gnus-summary-article-number))))
       t ; All non-existant numbers are the last article. :-)
-    (cdr (gnus-data-find-list article))))
+    (not (cdr (gnus-data-find-list article)))))
 
 (defun gnus-summary-insert-dummy-line (gnus-tmp-subject gnus-tmp-number)
   "Insert a dummy root in the summary buffer."
   (beginning-of-line)
-  (add-text-properties
+  (gnus-add-text-properties
    (point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
    (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
 
-(defvar gnus-thread-indent-array nil)
-(defvar gnus-thread-indent-array-level gnus-thread-indent-level)
 (defun gnus-make-thread-indent-array ()
   (let ((n 200))
-    (if (and gnus-thread-indent-array
-            (= gnus-thread-indent-level gnus-thread-indent-array-level))
-       nil
+    (unless (and gnus-thread-indent-array
+                (= gnus-thread-indent-level gnus-thread-indent-array-level))
       (setq gnus-thread-indent-array (make-vector 201 "")
            gnus-thread-indent-array-level gnus-thread-indent-level)
       (while (>= n 0)
@@ -7167,7 +7631,7 @@ article number."
     (when (string= gnus-tmp-name "")
       (setq gnus-tmp-name gnus-tmp-from))
     (or (numberp gnus-tmp-lines) (setq gnus-tmp-lines 0))
-    (put-text-property
+    (gnus-put-text-property
      (point)
      (progn (eval gnus-summary-line-format-spec) (point))
      'gnus-number gnus-tmp-number)
@@ -7220,7 +7684,7 @@ article number."
            1)
           ((memq (mail-header-number (car thread)) gnus-newsgroup-limit)
            1)
-          (t 1))))
+          (t 0))))
     (when (and level (zerop level) gnus-tmp-new-adopts)
       (incf number
            (apply '+ (mapcar
@@ -7241,12 +7705,14 @@ article number."
       (and (consp elem)                        ; Has to be a cons.
           (consp (cdr elem))           ; The cdr has to be a list.
           (symbolp (car elem))         ; Has to be a symbol in there.
+          (not (memq (car elem) 
+                     '(quit-config to-address to-list to-group)))
           (progn                       ; So we set it.
             (make-local-variable (car elem))
             (set (car elem) (eval (nth 1 elem))))))))
 
-(defun gnus-summary-read-group
-  (group &optional show-all no-article kill-buffer no-display)
+(defun gnus-summary-read-group (group &optional show-all no-article
+                                     kill-buffer no-display)
   "Start reading news in newsgroup GROUP.
 If SHOW-ALL is non-nil, already read articles are also listed.
 If NO-ARTICLE is non-nil, no article is selected initially.
@@ -7325,7 +7791,15 @@ If NO-DISPLAY, don't generate a summary buffer."
       (when gnus-build-sparse-threads
        (gnus-build-sparse-threads))
       ;; Find the initial limit.
-      (gnus-summary-initial-limit show-all)
+      (if gnus-show-threads
+         (if show-all
+             (let ((gnus-newsgroup-dormant nil))
+               (gnus-summary-initial-limit show-all))
+           (gnus-summary-initial-limit show-all))
+       (setq gnus-newsgroup-limit 
+             (mapcar 
+              (lambda (header) (mail-header-number header))
+              gnus-newsgroup-headers)))
       ;; Generate the summary buffer.
       (unless no-display
        (gnus-summary-prepare))
@@ -7365,9 +7839,10 @@ If NO-DISPLAY, don't generate a summary buffer."
                 (not no-display)
                 gnus-newsgroup-unreads
                 gnus-auto-select-first)
-           (if (eq gnus-auto-select-first 'best)
-               (gnus-summary-best-unread-article)
-             (gnus-summary-first-unread-article))
+           (unless (if (eq gnus-auto-select-first 'best)
+                       (gnus-summary-best-unread-article)
+                     (gnus-summary-first-unread-article))
+             (gnus-configure-windows 'summary))
          ;; Don't select any articles, just move point to the first
          ;; article in the group.
          (goto-char (point-min))
@@ -7379,11 +7854,11 @@ If NO-DISPLAY, don't generate a summary buffer."
          (gnus-request-asynchronous gnus-newsgroup-name gnus-newsgroup-data))
        (when kill-buffer
          (gnus-kill-or-deaden-summary kill-buffer))
-       (when (get-buffer-window gnus-group-buffer)
+       (when (get-buffer-window gnus-group-buffer t)
          ;; Gotta use windows, because recenter does wierd stuff if
          ;; the current buffer ain't the displayed window.
          (let ((owin (selected-window)))
-           (select-window (get-buffer-window gnus-group-buffer))
+           (select-window (get-buffer-window gnus-group-buffer t))
            (when (gnus-group-goto-group group)
              (recenter))
            (select-window owin))))
@@ -7422,38 +7897,39 @@ If NO-DISPLAY, don't generate a summary buffer."
          (result threads)
          subject hthread whole-subject)
       (while threads
-       (setq whole-subject (mail-header-subject (car (car threads))))
+       (setq whole-subject (mail-header-subject (caar threads)))
+       (setq subject
+             (cond
+              ;; Truncate the subject.
+              ((numberp gnus-summary-gather-subject-limit)
+               (setq subject (gnus-simplify-subject-re whole-subject))
+               (if (> (length subject) gnus-summary-gather-subject-limit)
+                   (substring subject 0 gnus-summary-gather-subject-limit)
+                 subject))
+              ;; Fuzzily simplify it.
+              ((eq 'fuzzy gnus-summary-gather-subject-limit)
+               (gnus-simplify-subject-fuzzy whole-subject))
+              ;; Just remove the leading "Re:".
+              (t
+               (gnus-simplify-subject-re whole-subject))))
+
        (if (and gnus-summary-gather-exclude-subject
                 (string-match gnus-summary-gather-exclude-subject
-                              whole-subject))
-           () ; We don't want to do anything with this article.
+                              subject))
+           ()          ; We don't want to do anything with this article.
          ;; We simplify the subject before looking it up in the
          ;; hash table.
-         (setq subject
-               (cond
-                ;; Truncate the subject.
-                ((numberp gnus-summary-gather-subject-limit)
-                 (setq subject (gnus-simplify-subject-re whole-subject))
-                 (if (> (length subject) gnus-summary-gather-subject-limit)
-                     (substring subject 0 gnus-summary-gather-subject-limit)
-                   subject))
-                ;; Fuzzily simplify it.
-                ((eq 'fuzzy gnus-summary-gather-subject-limit)
-                 (gnus-simplify-subject-fuzzy whole-subject))
-                ;; Just remove the leading "Re:".
-                (t
-                 (gnus-simplify-subject-re whole-subject))))
 
          (if (setq hthread (gnus-gethash subject hashtb))
              (progn
                ;; We enter a dummy root into the thread, if we
                ;; haven't done that already.
-               (unless (stringp (car (car hthread)))
+               (unless (stringp (caar hthread))
                  (setcar hthread (list whole-subject (car hthread))))
                ;; We add this new gathered thread to this gathered
                ;; thread.
                (setcdr (car hthread)
-                       (nconc (cdr (car hthread)) (list (car threads))))
+                       (nconc (cdar hthread) (list (car threads))))
                ;; Remove it from the list of threads.
                (setcdr prev (cdr threads))
                (setq threads prev))
@@ -7463,7 +7939,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        (setq threads (cdr threads)))
       result)))
 
-(defun gnus-summary-gather-threads-by-references (threads)
+(defun gnus-gather-threads-by-references (threads)
   "Gather threads by looking at References headers."
   (let ((idhashtb (gnus-make-hashtable 1023))
        (thhashtb (gnus-make-hashtable 1023))
@@ -7506,9 +7982,9 @@ If NO-DISPLAY, don't generate a summary buffer."
   "Sort subtreads inside each gathered thread by article number."
   (let ((result threads))
     (while threads
-      (when (stringp (car (car threads)))
+      (when (stringp (caar threads))
        (setcdr (car threads)
-               (sort (cdr (car threads)) 'gnus-thread-sort-by-number)))
+               (sort (cdar threads) 'gnus-thread-sort-by-number)))
       (setq threads (cdr threads)))
     result))
 
@@ -7539,15 +8015,14 @@ If NO-DISPLAY, don't generate a summary buffer."
        (when (and (setq references (mail-header-references header))
                   (not (string= references "")))
          (insert references)
-         (setq child (downcase (mail-header-id header))
+         (setq child (mail-header-id header)
                subject (mail-header-subject header))
          (setq generation 0)
          (while (search-backward ">" nil t)
            (setq end (1+ (point)))
            (when (search-backward "<" nil t)
              (push (list (incf generation) 
-                         child (setq child (downcase
-                                            (buffer-substring (point) end)))
+                         child (setq child (buffer-substring (point) end))
                          subject)
                    relations)))
          (push (list (1+ generation) child nil subject) relations)
@@ -7593,7 +8068,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        (when (not (car (symbol-value refs)))
         (setq heads (cdr (symbol-value refs)))
         (while heads
-          (if (memq (mail-header-number (car (car heads)))
+          (if (memq (mail-header-number (caar heads))
                     gnus-newsgroup-dormant)
               (setq heads (cdr heads))
             (setq id (symbol-name refs))
@@ -7620,12 +8095,11 @@ If NO-DISPLAY, don't generate a summary buffer."
                                 (regexp-quote id))))
            (or found (beginning-of-line 2)))
          (when found
-           (let (ref)
-             (beginning-of-line)
-             (and
-              (setq header (gnus-nov-parse-line
-                            (read (current-buffer)) deps))
-              (gnus-parent-id (mail-header-references header))))))
+           (beginning-of-line)
+           (and
+            (setq header (gnus-nov-parse-line
+                          (read (current-buffer)) deps))
+            (gnus-parent-id (mail-header-references header)))))
       (when header
        (let ((number (mail-header-number header)))
          (push number gnus-newsgroup-limit)
@@ -7637,20 +8111,41 @@ If NO-DISPLAY, don't generate a summary buffer."
                      (delq number gnus-newsgroup-unselected)))
            (push number gnus-newsgroup-ancient)))))))
 
-(defun gnus-summary-update-article (article &optional header)
+(defun gnus-summary-update-article (article &optional iheader)
   "Update ARTICLE in the summary buffer."
-  (let ((id (mail-header-id (gnus-summary-article-header article)))
-       (data (gnus-data-find article)))
-    (setcar (gnus-id-to-thread id) nil)
-    (gnus-summary-insert-subject id)
-    ;; Set the (possibly) new article number in the data structure.
-    (gnus-data-set-number data (gnus-id-to-article id))))
+  (set-buffer gnus-summary-buffer)
+  (let* ((header (or iheader (gnus-summary-article-header article)))
+        (id (mail-header-id header))
+        (data (gnus-data-find article))
+        (thread (gnus-id-to-thread id))
+        (references (mail-header-references header))
+        (parent
+         (gnus-id-to-thread
+          (or (gnus-parent-id 
+               (if (and references
+                        (not (equal "" references)))
+                   references))
+              "none")))
+        (buffer-read-only nil)
+        (old (car thread))
+        (number (mail-header-number header))
+        pos)
+    (when thread
+      ;; !!! Should this be in or not?
+      (unless iheader
+       (setcar thread nil))
+      (when parent
+       (delq thread parent))
+      (if (gnus-summary-insert-subject id header iheader)
+         ;; Set the (possibly) new article number in the data structure.
+         (gnus-data-set-number data (gnus-id-to-article id))
+       (setcar thread old)
+       nil))))
 
 (defun gnus-rebuild-thread (id)
   "Rebuild the thread containing ID."
-  (let ((dep gnus-newsgroup-dependencies)
-       (buffer-read-only nil)
-       current headers refs thread art data)
+  (let ((buffer-read-only nil)
+       current thread data)
     (if (not gnus-show-threads)
        (setq thread (list (car (gnus-id-to-thread id))))
       ;; Get the thread this article is part of.
@@ -7666,7 +8161,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        (while thread
          (unless (memq (setq thr (gnus-id-to-thread
                                      (gnus-root-id
-                                      (mail-header-id (car (car thread))))))
+                                      (mail-header-id (caar thread)))))
                        roots)
            (push thr roots))
          (setq thread (cdr thread)))
@@ -7675,11 +8170,10 @@ If NO-DISPLAY, don't generate a summary buffer."
            ;; All the loose roots are now one solid root.
            (setq thread (car roots))
          (setq thread (cons subject (gnus-sort-threads roots))))))
-    (let ((beg (point))
-         threads)
+    (let (threads)
       ;; We then insert this thread into the summary buffer.
       (let (gnus-newsgroup-data gnus-newsgroup-threads)
-       (gnus-summary-prepare-threads (list thread))
+       (gnus-summary-prepare-threads (gnus-cut-threads (list thread)))
        (setq data (nreverse gnus-newsgroup-data))
        (setq threads gnus-newsgroup-threads))
       ;; We splice the new data into the data structure.
@@ -7687,14 +8181,24 @@ If NO-DISPLAY, don't generate a summary buffer."
       (gnus-data-compute-positions)
       (setq gnus-newsgroup-threads (nconc threads gnus-newsgroup-threads)))))
 
+(defun gnus-number-to-header (number)
+  "Return the header for article NUMBER."
+  (let ((headers gnus-newsgroup-headers))
+    (while (and headers
+               (not (= number (mail-header-number (car headers)))))
+      (pop headers))
+    (when headers
+      (car headers))))
+
 (defun gnus-id-to-thread (id)
   "Return the (sub-)thread where ID appears."
-  (gnus-gethash (downcase id) gnus-newsgroup-dependencies))
+  (gnus-gethash id gnus-newsgroup-dependencies))
 
 (defun gnus-id-to-article (id)
   "Return the article number of ID."
   (let ((thread (gnus-id-to-thread id)))
-    (when thread
+    (when (and thread
+              (car thread))
       (mail-header-number (car thread)))))
 
 (defun gnus-id-to-header (id)
@@ -7704,23 +8208,23 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defun gnus-article-displayed-root-p (article)
   "Say whether ARTICLE is a root(ish) article."
   (let ((level (gnus-summary-thread-level article))
+       (refs (mail-header-references  (gnus-summary-article-header article)))
        particle)
     (cond 
      ((null level) nil)
      ((zerop level) t)
+     ((null refs) t)
+     ((null (gnus-parent-id refs)) t)
      ((and (= 1 level)
           (null (setq particle (gnus-id-to-article
-                                (gnus-parent-id 
-                                 (mail-header-references 
-                                  (gnus-summary-article-header article))))))
+                                (gnus-parent-id refs))))
           (null (gnus-summary-thread-level particle)))))))
 
 (defun gnus-root-id (id)
   "Return the id of the root of the thread where ID appears."
   (let (last-id prev)
-    (while (and id (setq prev (car (gnus-gethash
-                                   (downcase id)
-                                   gnus-newsgroup-dependencies))))
+    (while (and id (setq prev (car (gnus-gethash 
+                                   id gnus-newsgroup-dependencies))))
       (setq last-id id
            id (gnus-parent-id (mail-header-references prev))))
     last-id))
@@ -7728,11 +8232,11 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defun gnus-remove-thread (id &optional dont-remove)
   "Remove the thread that has ID in it."
   (let ((dep gnus-newsgroup-dependencies)
-       headers thread prev last-id)
+       headers thread last-id)
     ;; First go up in this thread until we find the root.
     (setq last-id (gnus-root-id id))
     (setq headers (list (car (gnus-id-to-thread last-id))
-                       (car (car (cdr (gnus-id-to-thread last-id))))))
+                       (caadr (gnus-id-to-thread last-id))))
     ;; We have now found the real root of this thread. It might have
     ;; been gathered into some loose thread, so we have to search
     ;; through the threads to find the thread we wanted.
@@ -7747,7 +8251,7 @@ If NO-DISPLAY, don't generate a summary buffer."
            (progn
              (setq sub (cdr sub))
              (while sub
-               (when (member (car (car sub)) headers)
+               (when (member (caar sub) headers)
                  (setq thread (car threads)
                        threads nil
                        sub nil))
@@ -7761,7 +8265,7 @@ If NO-DISPLAY, don't generate a summary buffer."
       (if thread
          (unless dont-remove
            (setq gnus-newsgroup-threads (delq thread gnus-newsgroup-threads)))
-       (setq thread (gnus-gethash (downcase last-id) dep)))
+       (setq thread (gnus-gethash last-id dep)))
       (when thread
        (prog1
            thread ; We return this thread.
@@ -7790,8 +8294,7 @@ If NO-DISPLAY, don't generate a summary buffer."
       (gnus-data-remove number))
     (setq thread (cdr thread))
     (while thread
-      (gnus-remove-thread-1 (car thread))
-      (setq thread (cdr thread)))))
+      (gnus-remove-thread-1 (pop thread)))))
 
 (defun gnus-sort-threads (threads)
   "Sort THREADS."
@@ -7879,8 +8382,8 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defsubst gnus-article-sort-by-date (h1 h2)
   "Sort articles by root article date."
   (string-lessp
-   (gnus-sortable-date (mail-header-date h1))
-   (gnus-sortable-date (mail-header-date h2))))
+   (inline (gnus-sortable-date (mail-header-date h1)))
+   (inline (gnus-sortable-date (mail-header-date h2)))))
 
 (defun gnus-thread-sort-by-date (h1 h2)
   "Sort threads by root article date."
@@ -7909,12 +8412,15 @@ Unscored articles will be counted as having a score of zero."
 
 (defun gnus-thread-total-score (thread)
   ;;  This function find the total score of THREAD.
-  (if (consp thread)
-      (if (stringp (car thread))
-         (apply gnus-thread-score-function 0
-                (mapcar 'gnus-thread-total-score-1 (cdr thread)))
-       (gnus-thread-total-score-1 thread))
-    (gnus-thread-total-score-1 (list thread))))
+  (cond ((null thread)
+        0)
+       ((consp thread)
+        (if (stringp (car thread))
+            (apply gnus-thread-score-function 0
+                   (mapcar 'gnus-thread-total-score-1 (cdr thread)))
+          (gnus-thread-total-score-1 thread)))
+       (t
+        (gnus-thread-total-score-1 (list thread)))))
 
 (defun gnus-thread-total-score-1 (root)
   ;; This function find the total score of the thread below ROOT.
@@ -7923,7 +8429,7 @@ Unscored articles will be counted as having a score of zero."
         (or (cdr (assq (mail-header-number root) gnus-newsgroup-scored))
             gnus-summary-default-score 0)
         (mapcar 'gnus-thread-total-score
-                (cdr (gnus-gethash (downcase (mail-header-id root))
+                (cdr (gnus-gethash (mail-header-id root)
                                    gnus-newsgroup-dependencies)))))
 
 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
@@ -7967,31 +8473,31 @@ or a straight list of headers."
        (if (and (= gnus-tmp-level 0)
                 (not (setq gnus-tmp-dummy-line nil))
                 (or (not stack)
-                    (= (car (car stack)) 0))
+                    (= (caar stack) 0))
                 (not gnus-tmp-false-parent)
                 (or gnus-tmp-new-adopts new-roots))
            (if gnus-tmp-new-adopts
                (setq gnus-tmp-level (if gnus-tmp-root-expunged 0 1)
                      thread (list (car gnus-tmp-new-adopts))
-                     gnus-tmp-header (car (car thread))
+                     gnus-tmp-header (caar thread)
                      gnus-tmp-new-adopts (cdr gnus-tmp-new-adopts))
              (if new-roots
                  (setq thread (list (car new-roots))
-                       gnus-tmp-header (car (car thread))
+                       gnus-tmp-header (caar thread)
                        new-roots (cdr new-roots))))
 
          (if threads
              ;; If there are some threads, we do them before the
              ;; threads on the stack.
              (setq thread threads
-                   gnus-tmp-header (car (car thread)))
+                   gnus-tmp-header (caar thread))
            ;; There were no current threads, so we pop something off
            ;; the stack.
            (setq state (car stack)
                  gnus-tmp-level (car state)
                  thread (cdr state)
                  stack (cdr stack)
-                 gnus-tmp-header (car (car thread)))))
+                 gnus-tmp-header (caar thread))))
 
        (setq gnus-tmp-false-parent nil)
        (setq gnus-tmp-root-expunged nil)
@@ -8003,14 +8509,14 @@ or a straight list of headers."
             ((eq gnus-summary-make-false-root 'adopt)
              ;; We let the first article adopt the rest.
              (setq gnus-tmp-new-adopts (nconc gnus-tmp-new-adopts
-                                              (cdr (cdr (car thread)))))
+                                              (cddar thread)))
              (setq gnus-tmp-gathered
                    (nconc (mapcar
                            (lambda (h) (mail-header-number (car h)))
-                           (cdr (cdr (car thread))))
+                           (cddar thread))
                           gnus-tmp-gathered))
-             (setq thread (cons (list (car (car thread))
-                                      (car (cdr (car thread))))
+             (setq thread (cons (list (caar thread)
+                                      (cadar thread))
                                 (cdr thread)))
              (setq gnus-tmp-level -1
                    gnus-tmp-false-parent t))
@@ -8019,7 +8525,7 @@ or a straight list of headers."
              (setq gnus-tmp-gathered
                    (nconc (mapcar
                            (lambda (h) (mail-header-number (car h)))
-                           (cdr (cdr (car thread))))
+                           (cddar thread))
                           gnus-tmp-gathered))
              (setq gnus-tmp-level -1))
             ((eq gnus-summary-make-false-root 'dummy)
@@ -8053,11 +8559,11 @@ or a straight list of headers."
            (setq gnus-tmp-gathered
                  (nconc (mapcar
                          (lambda (h) (mail-header-number (car h)))
-                         (cdr (car thread)))
+                         (cdar thread))
                         gnus-tmp-gathered))
-           (setq gnus-tmp-new-adopts (if (cdr (car thread))
+           (setq gnus-tmp-new-adopts (if (cdar thread)
                                          (append gnus-tmp-new-adopts
-                                                 (cdr (car thread)))
+                                                 (cdar thread))
                                        gnus-tmp-new-adopts)
                  thread-end t
                  gnus-tmp-header nil)
@@ -8067,7 +8573,10 @@ or a straight list of headers."
           ((and gnus-summary-mark-below
                 (< (or (cdr (assq number gnus-newsgroup-scored))
                        default-score)
-                   gnus-summary-mark-below))
+                   gnus-summary-mark-below)
+                ;; Don't touch sparse articles.
+                (not (memq number gnus-newsgroup-sparse))
+                (not (memq number gnus-newsgroup-ancient)))
            (setq gnus-newsgroup-unreads
                  (delq number gnus-newsgroup-unreads))
            (if gnus-newsgroup-auto-expire
@@