*** empty log message ***
[gnus] / lisp / gnus.el
index 32ad094..31c5e1c 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.35"
+(defconst gnus-version-number "5.2.24"
   "Version number for this version of Gnus.")
 
+(defconst gnus-version (format "Gnus v%s" gnus-version-number)
+  "Version string for this version of Gnus.")
+
 (defvar gnus-info-nodes
-  '((gnus-group-mode           "(gnus)The Group Buffer")
-    (gnus-summary-mode         "(gnus)The Summary Buffer")
-    (gnus-article-mode         "(gnus)The Article Buffer"))
-  "Assoc list of major modes and related Info nodes.")
+  '((gnus-group-mode "(gnus)The Group Buffer")
+    (gnus-summary-mode "(gnus)The Summary Buffer")
+    (gnus-article-mode "(gnus)The Article Buffer")
+    (gnus-server-mode "(gnus)The Server Buffer")
+    (gnus-browse-mode "(gnus)Browse Foreign Server")
+    (gnus-tree-mode "(gnus)Tree Display")
+    )
+  "Alist of major modes and related Info nodes.")
 
 (defvar gnus-group-buffer "*Group*")
 (defvar gnus-summary-buffer "*Summary*")
@@ -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,76 +3411,100 @@ 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.
        (select-window all-visible)
 
       ;; Either remove all windows or just remove all Gnus windows.
-      (if gnus-use-full-window
-         (mapcar (lambda (frame)
-                   (select-frame frame)
-                   (delete-other-windows)) 
-                 (frame-list))
-       (gnus-remove-some-windows)
-       (switch-to-buffer nntp-server-buffer))
+      (let ((frame (selected-frame)))
+       (unwind-protect
+           (if gnus-use-full-window
+               ;; We want to remove all other windows.
+               (if (not gnus-frame-split-p)
+                   ;; This is not a `frame' split, so we ignore the
+                   ;; other frames.  
+                   (delete-other-windows)
+                 ;; This is a `frame' split, so we delete all windows
+                 ;; on all frames.
+                 (mapcar 
+                  (lambda (frame)
+                    (unless (eq (cdr (assq 'minibuffer
+                                           (frame-parameters frame)))
+                                'only)
+                      (select-frame frame)
+                      (delete-other-windows)))
+                  (frame-list)))
+             ;; Just remove some windows.
+             (gnus-remove-some-windows)
+             (switch-to-buffer nntp-server-buffer))
+         (select-frame frame)))
 
       (switch-to-buffer nntp-server-buffer)
       (gnus-configure-frame split (get-buffer-window (current-buffer))))))
 
 (defun gnus-all-windows-visible-p (split)
-  (when (vectorp split)
-    (setq split (append split nil)))
-  (when (or (consp (car split))
-           (vectorp (car split)))
-    (push 1.0 split)
-    (push 'vertical split))
-  ;; The SPLIT might be something that is to be evaled to
-  ;; return a new SPLIT.
-  (while (and (not (assq (car split) gnus-window-to-buffer))
-             (gnus-functionp (car split)))
-    (setq split (eval split)))
-  (let* ((type (elt split 0)))
-    (cond
-     ((null split)
-      t)
-     ((not (or (eq type 'horizontal) (eq type 'vertical) (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)))
@@ -3332,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
@@ -3347,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)
@@ -3369,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)
@@ -3380,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."
@@ -3393,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)))
 
@@ -3427,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))
@@ -3475,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
@@ -3502,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)
@@ -3535,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.
@@ -3570,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)
@@ -3583,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)
@@ -3608,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."
@@ -3758,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))))
@@ -3779,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
@@ -3789,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)))
@@ -3802,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)))
 
@@ -3842,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))))
@@ -3877,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.
@@ -4050,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")
@@ -4064,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
@@ -4087,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)
@@ -4151,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)
@@ -4246,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
@@ -4281,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)
@@ -4305,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)))))))
@@ -4343,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
@@ -4378,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)
@@ -4393,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"))
@@ -4421,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))
@@ -4442,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))
@@ -4458,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."
@@ -4513,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.
@@ -4530,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))
@@ -4548,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
@@ -4569,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)
@@ -4584,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."
@@ -4616,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
@@ -4648,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)
@@ -4662,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.
@@ -4677,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))
@@ -4695,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)))
@@ -4710,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."
@@ -4764,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."
@@ -4821,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))
 
@@ -4850,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
@@ -4894,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."
@@ -4911,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))))
@@ -4939,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)))
@@ -5019,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.
@@ -5029,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)
@@ -5051,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."
@@ -5149,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
@@ -5194,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))
@@ -5249,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)))
 
@@ -5284,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))
@@ -5300,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"))
@@ -5323,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
@@ -5360,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)))
 
@@ -5402,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))
@@ -5436,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.
@@ -5455,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.
@@ -5480,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.
@@ -5507,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."
@@ -5661,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
@@ -5673,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
@@ -5689,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)))
@@ -5750,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)
@@ -5782,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)
@@ -5826,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)
@@ -5841,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
@@ -5915,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
@@ -5927,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)
@@ -5957,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))
@@ -6008,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)
@@ -6053,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.
@@ -6062,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)
@@ -6070,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)
@@ -6089,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))
@@ -6105,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)
@@ -6114,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)
@@ -6158,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"))
@@ -6170,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")))))
 
@@ -6190,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))))
@@ -6212,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.
@@ -6255,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))
@@ -6280,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."
@@ -6326,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."
@@ -6350,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)))))
@@ -6397,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."
@@ -6441,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)
@@ -6470,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
-   "v" gnus-summary-verbose-headers
-   "\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
-   "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)
@@ -6787,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)
@@ -6809,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
@@ -6839,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)))))
@@ -6894,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
@@ -6921,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)))
@@ -6959,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."
@@ -7004,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
@@ -7035,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
@@ -7045,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.
 
@@ -7069,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)))
@@ -7084,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)
@@ -7093,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)
@@ -7164,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)
@@ -7217,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
@@ -7238,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.
@@ -7322,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))
@@ -7333,14 +7810,16 @@ If NO-DISPLAY, don't generate a summary buffer."
       ;; If the summary buffer is empty, but there are some low-scored
       ;; articles or some excluded dormants, we include these in the
       ;; buffer.
-      (when (zerop (buffer-size))
+      (when (and (zerop (buffer-size))
+                (not no-display))
        (cond (gnus-newsgroup-dormant
               (gnus-summary-limit-include-dormant))
              ((and gnus-newsgroup-scored show-all)
               (gnus-summary-limit-include-expunged))))
       ;; Function `gnus-apply-kill-file' must be called in this hook.
       (run-hooks 'gnus-apply-kill-hook)
-      (if (zerop (buffer-size))
+      (if (and (zerop (buffer-size))
+              (not no-display))
          (progn
            ;; This newsgroup is empty.
            (gnus-summary-catchup-and-exit nil t) ;Without confirmations.
@@ -7357,11 +7836,13 @@ If NO-DISPLAY, don't generate a summary buffer."
             (gnus-summary-hide-all-threads))
        ;; Show first unread article if requested.
        (if (and (not no-article)
+                (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))
@@ -7373,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))))
@@ -7416,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))
@@ -7457,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))
@@ -7500,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))
 
@@ -7533,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)
@@ -7587,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))
@@ -7614,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)
@@ -7631,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.
@@ -7660,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)))
@@ -7669,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.
@@ -7681,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)
@@ -7698,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))
@@ -7722,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.
@@ -7741,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))
@@ -7755,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.
@@ -7784,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."
@@ -7873,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."
@@ -7903,22 +8412,34 @@ 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.
+  ;; This function finds the total score of the thread below ROOT.
   (setq root (car root))
-  (apply gnus-thread-score-function
-        (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))
-                                   gnus-newsgroup-dependencies)))))
+  (let ((number (mail-header-number root)))
+    (if (and (not (memq number gnus-newsgroup-limit))
+            (not (memq number gnus-newsgroup-sparse)))
+       ;; This article shouldn't be counted.
+       (apply gnus-thread-score-function
+              (mapcar 'gnus-thread-total-score
+                      (cdr (gnus-gethash (mail-header-id root)
+                                         gnus-newsgroup-dependencies))))
+      ;; This article should be counted.
+      (apply gnus-thread-score-function
+            (or (cdr (assq number gnus-newsgroup-scored))
+                gnus-summary-default-score 0)
+            (mapcar 'gnus-thread-total-score
+                    (cdr (gnus-gethash (mail-header-id root)
+                                       gnus-newsgroup-dependencies)))))))
 
 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defvar gnus-tmp-prev-subject nil)
@@ -7961,31 +8482,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)
@@ -7997,14 +8518,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))
@@ -8013,7 +8534,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)
@@ -8047,11 +8568,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)
@@ -8061,7 +8582,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
@@ -8072,105 +8596,104 @@ or a straight list of headers."
          (when gnus-tmp-header
            ;; We may have an old dummy line to output before this
            ;; article.
-           (if gnus-tmp-dummy-line
-               (progn
-                 (gnus-summary-insert-dummy-line
-                  gnus-tmp-dummy-line (mail-header-number gnus-tmp-header))
-                 (setq gnus-tmp-dummy-line nil))
-
-             ;; Compute the mark.
-             (setq
-              gnus-tmp-unread
-              (cond
-               ((memq number gnus-newsgroup-unreads) gnus-unread-mark)
-               ((memq number gnus-newsgroup-marked) gnus-ticked-mark)
-               ((memq number gnus-newsgroup-dormant) gnus-dormant-mark)
-               ((memq number gnus-newsgroup-expirable) gnus-expirable-mark)
-               (t (or (cdr (assq number gnus-newsgroup-reads))
-                      gnus-ancient-mark))))
-
-             (push (gnus-data-make number gnus-tmp-unread (1+ (point))
-                                   gnus-tmp-header gnus-tmp-level)
-                   gnus-newsgroup-data)
-
-             ;; Actually insert the line.
-             (setq
-              gnus-tmp-subject-or-nil
-              (cond
-               ((and gnus-thread-ignore-subject
-                     gnus-tmp-prev-subject
-                     (not (inline (gnus-subject-equal
-                                   gnus-tmp-prev-subject subject))))
-                subject)
-               ((zerop gnus-tmp-level)
-                (if (and (eq gnus-summary-make-false-root 'empty)
-                         (memq number gnus-tmp-gathered)
-                         gnus-tmp-prev-subject
-                         (inline (gnus-subject-equal
-                                  gnus-tmp-prev-subject subject)))
-                    gnus-summary-same-subject
-                  subject))
-               (t gnus-summary-same-subject)))
-             (if (and (eq gnus-summary-make-false-root 'adopt)
-                      (= gnus-tmp-level 1)
-                      (memq number gnus-tmp-gathered))
-                 (setq gnus-tmp-opening-bracket ?\<
-                       gnus-tmp-closing-bracket ?\>)
-               (setq gnus-tmp-opening-bracket ?\[
-                     gnus-tmp-closing-bracket ?\]))
-             (setq
-              gnus-tmp-indentation
-              (aref gnus-thread-indent-array gnus-tmp-level)
-              gnus-tmp-lines (mail-header-lines gnus-tmp-header)
-              gnus-tmp-score (or (cdr (assq number gnus-newsgroup-scored))
-                                 gnus-summary-default-score 0)
-              gnus-tmp-score-char
-              (if (or (null gnus-summary-default-score)
-                      (<= (abs (- gnus-tmp-score gnus-summary-default-score))
-                          gnus-summary-zcore-fuzz)) ? 
-                (if (< gnus-tmp-score gnus-summary-default-score)
-                    gnus-score-below-mark gnus-score-over-mark))
-              gnus-tmp-replied
-              (cond ((memq number gnus-newsgroup-processable)
-                     gnus-process-mark)
-                    ((memq number gnus-newsgroup-cached)
-                     gnus-cached-mark)
-                    ((memq number gnus-newsgroup-replied)
-                     gnus-replied-mark)
-                    (t gnus-unread-mark))
-              gnus-tmp-from (mail-header-from gnus-tmp-header)
-              gnus-tmp-name
-              (cond
-               ((string-match "(.+)" gnus-tmp-from)
-                (substring gnus-tmp-from
-                           (1+ (match-beginning 0)) (1- (match-end 0))))
-               ((string-match "<[^>]+> *$" gnus-tmp-from)
-                (setq beg-match (match-beginning 0))
-                (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
-                         (substring gnus-tmp-from (1+ (match-beginning 0))
-                                    (1- (match-end 0))))
-                    (substring gnus-tmp-from 0 beg-match)))
-               (t gnus-tmp-from)))
-             (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
-              (point)
-              (progn (eval gnus-summary-line-format-spec) (point))
-              'gnus-number number)
-             (when gnus-visual-p
-               (forward-line -1)
-               (run-hooks 'gnus-summary-update-hook)
-               (forward-line 1))
-
-             )
+           (when gnus-tmp-dummy-line
+             (gnus-summary-insert-dummy-line
+              gnus-tmp-dummy-line (mail-header-number gnus-tmp-header))
+             (setq gnus-tmp-dummy-line nil))
+
+           ;; Compute the mark.
+           (setq
+            gnus-tmp-unread
+            (cond
+             ((memq number gnus-newsgroup-unreads) gnus-unread-mark)
+             ((memq number gnus-newsgroup-marked) gnus-ticked-mark)
+             ((memq number gnus-newsgroup-dormant) gnus-dormant-mark)
+             ((memq number gnus-newsgroup-expirable) gnus-expirable-mark)
+             (t (or (cdr (assq number gnus-newsgroup-reads))
+                    gnus-ancient-mark))))
+
+           (push (gnus-data-make number gnus-tmp-unread (1+ (point))
+                                 gnus-tmp-header gnus-tmp-level)
+                 gnus-newsgroup-data)
+
+           ;; Actually insert the line.
+           (setq
+            gnus-tmp-subject-or-nil
+            (cond
+             ((and gnus-thread-ignore-subject
+                   gnus-tmp-prev-subject
+                   (not (inline (gnus-subject-equal
+                                 gnus-tmp-prev-subject subject))))
+              subject)
+             ((zerop gnus-tmp-level)
+              (if (and (eq gnus-summary-make-false-root 'empty)
+                       (memq number gnus-tmp-gathered)
+                       gnus-tmp-prev-subject
+                       (inline (gnus-subject-equal
+                                gnus-tmp-prev-subject subject)))
+                  gnus-summary-same-subject
+                subject))
+             (t gnus-summary-same-subject)))
+           (if (and (eq gnus-summary-make-false-root 'adopt)
+                    (= gnus-tmp-level 1)
+                    (memq number gnus-tmp-gathered))
+               (setq gnus-tmp-opening-bracket ?\<
+                     gnus-tmp-closing-bracket ?\>)
+             (setq gnus-tmp-opening-bracket ?\[
+                   gnus-tmp-closing-bracket ?\]))
+           (setq
+            gnus-tmp-indentation
+            (aref gnus-thread-indent-array gnus-tmp-level)
+            gnus-tmp-lines (mail-header-lines gnus-tmp-header)
+            gnus-tmp-score (or (cdr (assq number gnus-newsgroup-scored))
+                               gnus-summary-default-score 0)
+            gnus-tmp-score-char
+            (if (or (null gnus-summary-default-score)
+                    (<= (abs (- gnus-tmp-score gnus-summary-default-score))
+                        gnus-summary-zcore-fuzz)) ? 
+              (if (< gnus-tmp-score gnus-summary-default-score)
+                  gnus-score-below-mark gnus-score-over-mark))
+            gnus-tmp-replied
+            (cond ((memq number gnus-newsgroup-processable)
+                   gnus-process-mark)
+                  ((memq number gnus-newsgroup-cached)
+                   gnus-cached-mark)
+                  ((memq number gnus-newsgroup-replied)
+                   gnus-replied-mark)
+                  ((memq number gnus-newsgroup-saved)
+                   gnus-saved-mark)
+                  (t gnus-unread-mark))
+            gnus-tmp-from (mail-header-from gnus-tmp-header)
+            gnus-tmp-name
+            (cond
+             ((string-match "(.+)" gnus-tmp-from)
+              (substring gnus-tmp-from
+                         (1+ (match-beginning 0)) (1- (match-end 0))))
+             ((string-match "<[^>]+> *$" gnus-tmp-from)
+              (setq beg-match (match-beginning 0))
+              (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
+                       (substring gnus-tmp-from (1+ (match-beginning 0))
+                                  (1- (match-end 0))))
+                  (substring gnus-tmp-from 0 beg-match)))
+             (t gnus-tmp-from)))
+           (when (string= gnus-tmp-name "")
+             (setq gnus-tmp-name gnus-tmp-from))
+           (or (numberp gnus-tmp-lines) (setq gnus-tmp-lines 0))
+           (gnus-put-text-property
+            (point)
+            (progn (eval gnus-summary-line-format-spec) (point))
+            'gnus-number number)
+           (when gnus-visual-p
+             (forward-line -1)
+             (run-hooks 'gnus-summary-update-hook)
+             (forward-line 1))
 
            (setq gnus-tmp-prev-subject subject)))
 
        (when (nth 1 thread)
          (push (cons (max 0 gnus-tmp-level) (nthcdr 1 thread)) stack))
        (incf gnus-tmp-level)
-       (setq threads (if thread-end nil (cdr (car thread))))
+       (setq threads (if thread-end nil (cdar thread)))
        (unless threads
          (setq gnus-tmp-level 0)))))
   (gnus-message 7 "Generating summary...done"))
@@ -8180,16 +8703,16 @@ or a straight list of headers."
   (let (header number mark)
 
     (while headers
-      (setq header (car headers)
-           headers (cdr headers)
-           number (mail-header-number header))
-
       ;; We may have to root out some bad articles...
-      (when (memq number gnus-newsgroup-limit)
+      (when (memq (setq number (mail-header-number
+                               (setq header (pop headers))))
+                 gnus-newsgroup-limit)
+       ;; Mark article as read when it has a low score.
        (when (and gnus-summary-mark-below
                   (< (or (cdr (assq number gnus-newsgroup-scored))
                          gnus-summary-default-score 0)
-                     gnus-summary-mark-below))
+                     gnus-summary-mark-below)
+                  (not (memq number gnus-newsgroup-ancient)))
          (setq gnus-newsgroup-unreads
                (delq number gnus-newsgroup-unreads))
          (if gnus-newsgroup-auto-expire
@@ -8227,12 +8750,19 @@ If READ-ALL is non-nil, all articles in the group are selected."
        (error "Couldn't open server"))
 
     (or (and entry (not (eq (car entry) t))) ; Either it's active...
-       (gnus-activate-group group) ; Or we can activate it...
-       (progn ; Or we bug out.
-         (kill-buffer (current-buffer))
+       (gnus-activate-group group)     ; Or we can activate it...
+       (progn                          ; Or we bug out.
+         (when (equal major-mode 'gnus-summary-mode)
+           (kill-buffer (current-buffer)))
          (error "Couldn't request group %s: %s"
                 group (gnus-status-message group))))
 
+    (unless (gnus-request-group group t)
+      (when (equal major-mode 'gnus-summary-mode)
+       (kill-buffer (current-buffer)))
+      (error "Couldn't request group %s: %s"
+            group (gnus-status-message group)))      
+
     (setq gnus-newsgroup-name group)
     (setq gnus-newsgroup-unselected nil)
     (setq gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
@@ -8262,7 +8792,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
 
     (cond
      ((null articles)
-      (gnus-message 3 "Couldn't select newsgroup -- no articles to display")
+      ;;(gnus-message 3 "Couldn't select newsgroup -- no articles to display")
       'quit)
      ((eq articles 0) nil)
      (t
@@ -8270,7 +8800,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
       (setq gnus-newsgroup-dependencies
            (gnus-make-hashtable (length articles)))
       ;; Retrieve the headers and read them in.
-      (gnus-message 5 "Fetching headers...")
+      (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
       (setq gnus-newsgroup-headers
            (if (eq 'nov
                    (setq gnus-headers-retrieved-by
@@ -8285,7 +8815,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
                                    (> (length articles) 1))))))
                (gnus-get-newsgroup-headers-xover articles)
              (gnus-get-newsgroup-headers)))
-      (gnus-message 5 "Fetching headers...done")
+      (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name)
 
       ;; Kludge to avoid having cached articles nixed out in virtual groups.
       (when cached
@@ -8310,13 +8840,16 @@ If READ-ALL is non-nil, all articles in the group are selected."
       ;; Check whether auto-expire is to be done in this group.
       (setq gnus-newsgroup-auto-expire
            (gnus-group-auto-expirable-p group))
+      ;; Set up the article buffer now, if necessary.
+      (unless gnus-single-article-buffer
+       (gnus-article-setup-buffer))
       ;; First and last article in this newsgroup.
-      (and gnus-newsgroup-headers
-          (setq gnus-newsgroup-begin
-                (mail-header-number (car gnus-newsgroup-headers)))
-          (setq gnus-newsgroup-end
-                (mail-header-number
-                 (gnus-last-element gnus-newsgroup-headers))))
+      (when gnus-newsgroup-headers
+       (setq gnus-newsgroup-begin
+             (mail-header-number (car gnus-newsgroup-headers))
+             gnus-newsgroup-end
+             (mail-header-number
+              (gnus-last-element gnus-newsgroup-headers))))
       (setq gnus-reffed-article-number -1)
       ;; GROUP is successfully selected.
       (or gnus-newsgroup-headers t)))))
@@ -8354,7 +8887,8 @@ If READ-ALL is non-nil, all articles in the group are selected."
                           "How many articles from %s (default %d): "
                           gnus-newsgroup-name number))))
                    (if (string-match "^[ \t]*$" input) number input)))
-                ((and (> scored marked) (< scored number))
+                ((and (> scored marked) (< scored number)
+                      (> (- scored number) 20))
                  (let ((input
                         (read-string
                          (format "%s %s (%d scored, %d total): "
@@ -8458,7 +8992,7 @@ If READ-ALL is non-nil, all articles in the group are selected."
   (let ((types gnus-article-mark-lists)
        (info (gnus-get-info gnus-newsgroup-name))
        (uncompressed '(score bookmark killed))
-       var type list newmarked symbol)
+       type list newmarked symbol)
     (when info
       ;; Add all marks lists that are non-nil to the list of marks lists.
       (while types
@@ -8469,7 +9003,8 @@ If READ-ALL is non-nil, all articles in the group are selected."
                                                (car type))))))
          (push (cons (cdr type)
                      (if (memq (cdr type) uncompressed) list
-                       (gnus-compress-sequence (set symbol (sort list '<)) t)))
+                       (gnus-compress-sequence 
+                        (set symbol (sort list '<)) t)))
                newmarked)))
 
       ;; Enter these new marks into the info of the group.
@@ -8495,17 +9030,22 @@ If READ-ALL is non-nil, all articles in the group are selected."
        marked m)
     (or (not info)
        (and (not (setq marked (nthcdr 3 info)))
-            (setcdr (nthcdr 2 info)
-                    (list (list (cons type (gnus-compress-sequence
-                                            articles t))))))
+            (or (null articles)
+                (setcdr (nthcdr 2 info)
+                        (list (list (cons type (gnus-compress-sequence
+                                                articles t)))))))
        (and (not (setq m (assq type (car marked))))
-            (setcar marked
-                    (cons (cons type (gnus-compress-sequence articles t) )
-                          (car marked))))
+            (or (null articles)
+                (setcar marked
+                        (cons (cons type (gnus-compress-sequence articles t) )
+                              (car marked)))))
        (if force
-           (setcdr m (gnus-compress-sequence articles t))
+           (if (null articles)
+               (setcar (nthcdr 3 info)
+                       (delq (assq type (car marked)) (car marked)))
+             (setcdr m (gnus-compress-sequence articles t)))
          (setcdr m (gnus-compress-sequence
-                    (sort (nconc (gnus-uncompress-range m)
+                    (sort (nconc (gnus-uncompress-range (cdr m))
                                  (copy-sequence articles)) '<) t))))))
 
 (defun gnus-set-mode-line (where)
@@ -8539,12 +9079,13 @@ If WHERE is `summary', the summary mode line format will be used."
               (gnus-tmp-subject
                (if (and gnus-current-headers
                         (vectorp gnus-current-headers))
-                   (mail-header-subject gnus-current-headers) ""))
+                   (gnus-mode-string-quote
+                    (mail-header-subject gnus-current-headers)) ""))
               max-len
               gnus-tmp-header);; passed as argument to any user-format-funcs
          (setq mode-string (eval mformat))
          (setq max-len (max 4 (if gnus-mode-non-string-length
-                                  (- (frame-width)
+                                  (- (window-width)
                                      gnus-mode-non-string-length)
                                 (length mode-string))))
          ;; We might have to chop a bit of the string off...
@@ -8555,14 +9096,15 @@ If WHERE is `summary', the summary mode line format will be used."
          ;; Pad the mode string a bit.
          (setq mode-string (format (format "%%-%ds" max-len) mode-string))))
       ;; Update the mode line.
-      (setq mode-line-buffer-identification (list mode-string))
+      (setq mode-line-buffer-identification 
+           (gnus-mode-line-buffer-identification
+            (list mode-string)))
       (set-buffer-modified-p t))))
 
 (defun gnus-create-xref-hashtb (from-newsgroup headers unreads)
   "Go through the HEADERS list and add all Xrefs to a hash table.
 The resulting hash table is returned, or nil if no Xrefs were found."
-  (let* ((from-method (gnus-find-method-for-group from-newsgroup))
-        (virtual (gnus-virtual-group-p from-newsgroup))
+  (let* ((virtual (gnus-virtual-group-p from-newsgroup))
         (prefix (if virtual "" (gnus-group-real-prefix from-newsgroup)))
         (xref-hashtb (make-vector 63 0))
         start group entry number xrefs header)
@@ -8574,8 +9116,10 @@ The resulting hash table is returned, or nil if no Xrefs were found."
        (setq start 0)
        (while (string-match "\\([^ ]+\\)[:/]\\([0-9]+\\)" xrefs start)
          (setq start (match-end 0))
-         (setq group (concat prefix (substring xrefs (match-beginning 1)
-                                               (match-end 1))))
+         (setq group (if prefix
+                         (concat prefix (substring xrefs (match-beginning 1)
+                                                   (match-end 1)))
+                       (substring xrefs (match-beginning 1) (match-end 1))))
          (setq number
                (string-to-int (substring xrefs (match-beginning 2)
                                          (match-end 2))))
@@ -8673,8 +9217,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (while range
              (if (numberp (car range))
                  (setq num (1+ num))
-               (setq num (+ num (- (1+ (cdr (car range)))
-                                   (car (car range))))))
+               (setq num (+ num (- (1+ (cdar range)) (caar range)))))
              (setq range (cdr range)))
            (setq num (- (cdr active) num))))
          ;; Update the number of unread articles.
@@ -8705,8 +9248,9 @@ The resulting hash table is returned, or nil if no Xrefs were found."
        headers id id-dep ref-dep end ref)
     (save-excursion
       (set-buffer nntp-server-buffer)
+      (run-hooks 'gnus-parse-headers-hook)
       (let ((case-fold-search t)
-           in-reply-to header number p lines)
+           in-reply-to header p lines)
        (goto-char (point-min))
        ;; Search to the beginning of the next header.  Error messages
        ;; do not begin with 2 or 3.
@@ -8761,31 +9305,28 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (progn
              (goto-char p)
              (if (search-forward "\nreferences: " nil t)
-                 (prog1
-                     (gnus-header-value)
-                   (setq end (match-end 0))
-                   (save-excursion
+                 (progn
+                   (setq end (point))
+                   (prog1
+                       (gnus-header-value)
                      (setq ref
-                           (downcase
-                            (buffer-substring
-                             (progn
-                               (end-of-line)
-                               (search-backward ">" end t)
-                               (1+ (point)))
-                             (progn
-                               (search-backward "<" end t)
-                               (point)))))))
+                           (buffer-substring
+                            (progn
+                              (end-of-line)
+                              (search-backward ">" end t)
+                              (1+ (point)))
+                            (progn
+                              (search-backward "<" end t)
+                              (point))))))
                ;; Get the references from the in-reply-to header if there
                ;; were no references and the in-reply-to header looks
                ;; promising.
                (if (and (search-forward "\nin-reply-to: " nil t)
                         (setq in-reply-to (gnus-header-value))
                         (string-match "<[^>]+>" in-reply-to))
-                   (prog1
-                       (setq ref (substring in-reply-to (match-beginning 0)
-                                            (match-end 0)))
-                     (setq ref (downcase ref))))
-               (setq ref "")))
+                   (setq ref (substring in-reply-to (match-beginning 0)
+                                        (match-end 0)))
+                 (setq ref ""))))
            ;; Chars.
            0
            ;; Lines.
@@ -8800,31 +9341,27 @@ The resulting hash table is returned, or nil if no Xrefs were found."
              (goto-char p)
              (and (search-forward "\nxref: " nil t)
                   (gnus-header-value)))))
-         (if (and gnus-nocem-hashtb
-                  (gnus-gethash id gnus-nocem-hashtb))
-             ;; Banned article.
-             (setq header nil)
-           ;; We do the threading while we read the headers.  The
-           ;; message-id and the last reference are both entered into
-           ;; the same hash table.  Some tippy-toeing around has to be
-           ;; done in case an article has arrived before the article
-           ;; which it refers to.
-           (if (boundp (setq id-dep (intern (downcase id) dependencies)))
-               (if (and (car (symbol-value id-dep))
-                        (not force-new))
-                   ;; An article with this Message-ID has already
-                   ;; been seen, so we ignore this one, except we add
-                   ;; any additional Xrefs (in case the two articles
-                   ;; came from different servers).
-                   (progn
-                     (mail-header-set-xref
-                      (car (symbol-value id-dep))
-                      (concat (or (mail-header-xref
-                                   (car (symbol-value id-dep))) "")
-                              (or (mail-header-xref header) "")))
-                     (setq header nil))
-                 (setcar (symbol-value id-dep) header))
-             (set id-dep (list header))))
+         ;; We do the threading while we read the headers.  The
+         ;; message-id and the last reference are both entered into
+         ;; the same hash table.  Some tippy-toeing around has to be
+         ;; done in case an article has arrived before the article
+         ;; which it refers to.
+         (if (boundp (setq id-dep (intern id dependencies)))
+             (if (and (car (symbol-value id-dep))
+                      (not force-new))
+                 ;; An article with this Message-ID has already
+                 ;; been seen, so we ignore this one, except we add
+                 ;; any additional Xrefs (in case the two articles
+                 ;; came from different servers).
+                 (progn
+                   (mail-header-set-xref
+                    (car (symbol-value id-dep))
+                    (concat (or (mail-header-xref
+                                 (car (symbol-value id-dep))) "")
+                            (or (mail-header-xref header) "")))
+                   (setq header nil))
+               (setcar (symbol-value id-dep) header))
+           (set id-dep (list header)))
          (when header
            (if (boundp (setq ref-dep (intern ref dependencies)))
                (setcdr (symbol-value ref-dep)
@@ -8854,21 +9391,20 @@ The resulting hash table is returned, or nil if no Xrefs were found."
   '(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
 
 ;; Goes through the xover lines and returns a list of vectors
-(defun gnus-get-newsgroup-headers-xover (sequence &optional force-new)
+(defun gnus-get-newsgroup-headers-xover (sequence &optional 
+                                                 force-new dependencies)
   "Parse the news overview data in the server buffer, and return a
 list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
   ;; Get the Xref when the users reads the articles since most/some
   ;; NNTP servers do not include Xrefs when using XOVER.
   (setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
   (let ((cur nntp-server-buffer)
-       (dependencies gnus-newsgroup-dependencies)
+       (dependencies (or dependencies gnus-newsgroup-dependencies))
        number headers header)
     (save-excursion
       (set-buffer nntp-server-buffer)
       ;; Allow the user to mangle the headers before parsing them.
       (run-hooks 'gnus-parse-headers-hook)
-      ;; Allow the user to mangle the headers before parsing them.
-      (run-hooks 'gnus-parse-headers-hook)
       (goto-char (point-min))
       (while (and sequence (not (eobp)))
        (setq number (read cur))
@@ -8915,12 +9451,9 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
                     (search-forward "\t" eol)
                     (if (search-backward ">" beg t)
                         (setq ref
-                              (downcase
-                               (buffer-substring
-                                (1+ (point))
-                                (progn
-                                  (search-backward "<" beg t)
-                                  (point)))))
+                              (buffer-substring
+                               (1+ (point))
+                               (search-backward "<" beg t)))
                       (setq ref nil))))
                 (gnus-nov-field))      ; refs
               (gnus-nov-read-integer)  ; chars
@@ -8930,42 +9463,36 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
                 (gnus-nov-field))      ; misc
               ))
       (error (progn
-              (ding)
-              (gnus-message 4 "Strange nov line")
+              (gnus-error 4 "Strange nov line")
               (setq header nil)
               (goto-char eol))))
 
     (widen)
 
     ;; We build the thread tree.
-    (and header
-        (if (and gnus-nocem-hashtb
-                 (gnus-gethash id gnus-nocem-hashtb))
-            ;; Banned article.
-            (setq header nil)
-          (if (boundp (setq id-dep (intern (downcase id) dependencies)))
-              (if (and (car (symbol-value id-dep))
-                       (not force-new))
-                  ;; An article with this Message-ID has already been seen,
-                  ;; so we ignore this one, except we add any additional
-                  ;; Xrefs (in case the two articles came from different
-                  ;; servers.
-                  (progn
-                    (mail-header-set-xref
-                     (car (symbol-value id-dep))
-                     (concat (or (mail-header-xref
-                                  (car (symbol-value id-dep))) "")
-                             (or (mail-header-xref header) "")))
-                    (setq header nil))
-                (setcar (symbol-value id-dep) header))
-            (set id-dep (list header)))))
-    (if header
-       (progn
-         (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
-             (setcdr (symbol-value ref-dep)
-                     (nconc (cdr (symbol-value ref-dep))
-                            (list (symbol-value id-dep))))
-           (set ref-dep (list nil (symbol-value id-dep))))))
+    (when header
+      (if (boundp (setq id-dep (intern id dependencies)))
+         (if (and (car (symbol-value id-dep))
+                  (not force-new))
+             ;; An article with this Message-ID has already been seen,
+             ;; so we ignore this one, except we add any additional
+             ;; Xrefs (in case the two articles came from different
+             ;; servers.
+             (progn
+               (mail-header-set-xref
+                (car (symbol-value id-dep))
+                (concat (or (mail-header-xref
+                             (car (symbol-value id-dep))) "")
+                        (or (mail-header-xref header) "")))
+               (setq header nil))
+           (setcar (symbol-value id-dep) header))
+       (set id-dep (list header))))
+    (when header
+      (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
+         (setcdr (symbol-value ref-dep)
+                 (nconc (cdr (symbol-value ref-dep))
+                        (list (symbol-value id-dep))))
+       (set ref-dep (list nil (symbol-value id-dep)))))
     header))
 
 (defun gnus-article-get-xrefs ()
@@ -8991,15 +9518,31 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
                                               (progn (end-of-line) (point))))
                  (mail-header-set-xref headers xref))))))))
 
-(defun gnus-summary-insert-subject (id)
+(defun gnus-summary-insert-subject (id &optional old-header use-old-header)
   "Find article ID and insert the summary line for that article."
-  (let ((header (gnus-read-header id))
-       (number (and (numberp id) id)))
+  (let ((header (if (and old-header use-old-header)
+                   old-header (gnus-read-header id)))
+       (number (and (numberp id) id))
+       pos)
     (when header
       ;; Rebuild the thread that this article is part of and go to the
       ;; article we have fetched.
+      (when (and (not gnus-show-threads)
+                old-header)
+       (when (setq pos (text-property-any
+                        (point-min) (point-max) 'gnus-number 
+                        (mail-header-number old-header)))
+         (goto-char pos)
+         (gnus-delete-line)
+         (gnus-data-remove (mail-header-number old-header))))
+      (when old-header
+       (mail-header-set-number header (mail-header-number old-header)))
+      (setq gnus-newsgroup-sparse
+           (delq (setq number (mail-header-number header)) 
+                 gnus-newsgroup-sparse))
+      (setq gnus-newsgroup-ancient (delq number gnus-newsgroup-ancient))
       (gnus-rebuild-thread (mail-header-id header))
-      (gnus-summary-goto-subject (setq number (mail-header-number header))))
+      (gnus-summary-goto-subject number nil t))
     (when (and (numberp number)
               (> number 0))
       ;; We have to update the boundaries even if we can't fetch the
@@ -9013,17 +9556,17 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
       (setq gnus-newsgroup-unselected
            (delq number gnus-newsgroup-unselected)))
     ;; Report back a success?
-    (and header number)))
+    (and header (mail-header-number header))))
 
 (defun gnus-summary-work-articles (n)
   "Return a list of articles to be worked upon.         The prefix argument,
 the list of process marked articles, and the current article will be
 taken into consideration."
   (cond
-   ((and n (numberp n))
+   (n
     ;; A numerical prefix has been given.
     (let ((backward (< n 0))
-         (n (abs n))
+         (n (abs (prefix-numeric-value n)))
          articles article)
       (save-excursion
        (while
@@ -9075,12 +9618,14 @@ If EXCLUDE-GROUP, do not go to this group."
 
 (defun gnus-summary-find-next (&optional unread article backward)
   (if backward (gnus-summary-find-prev)
-    (let* ((article (or article (gnus-summary-article-number)))
+    (let* ((dummy (gnus-summary-article-intangible-p))
+          (article (or article (gnus-summary-article-number)))
           (arts (gnus-data-find-list article))
           result)
-      (when (or (not gnus-summary-check-current)
-               (not unread)
-               (not (gnus-data-unread-p (car arts))))
+      (when (and (not dummy)
+                (or (not gnus-summary-check-current)
+                    (not unread)
+                    (not (gnus-data-unread-p (car arts)))))
        (setq arts (cdr arts)))
       (when (setq result
                  (if unread
@@ -9096,12 +9641,14 @@ If EXCLUDE-GROUP, do not go to this group."
        (gnus-data-number result)))))
 
 (defun gnus-summary-find-prev (&optional unread article)
-  (let* ((article (or article (gnus-summary-article-number)))
+  (let* ((eobp (eobp))
+        (article (or article (gnus-summary-article-number)))
         (arts (gnus-data-find-list article (gnus-data-list 'rev)))
         result)
-    (when (or (not gnus-summary-check-current)
-             (not unread)
-             (not (gnus-data-unread-p (car arts))))
+    (when (and (not eobp)
+              (or (not gnus-summary-check-current)
+                  (not unread)
+                  (not (gnus-data-unread-p (car arts)))))
       (setq arts (cdr arts)))
     (if (setq result
              (if unread
@@ -9141,19 +9688,21 @@ If EXCLUDE-GROUP, do not go to this group."
         (gnus-data-number result))))
 
 (defun gnus-summary-search-forward (&optional unread subject backward)
-  (cond (subject
-        (gnus-summary-find-subject subject unread backward))
-       (backward
-        (gnus-summary-find-prev unread))
-       (t
-        (gnus-summary-find-next unread))))
-
-(defun gnus-recenter ()
+  "Search forward for an article.
+If UNREAD, look for unread articles.  If SUBJECT, look for
+articles with that subject.  If BACKWARD, search backward instead."
+  (cond (subject (gnus-summary-find-subject subject unread backward))
+       (backward (gnus-summary-find-prev unread))
+       (t (gnus-summary-find-next unread))))
+
+(defun gnus-recenter (&optional n)
   "Center point in window and redisplay frame.
 Also do horizontal recentering."
-  (interactive)
-  (gnus-horizontal-recenter)
-  (recenter))
+  (interactive "P")
+  (when (and gnus-auto-center-summary
+            (not (eq gnus-auto-center-summary 'vertical)))
+    (gnus-horizontal-recenter))
+  (recenter n))
 
 (defun gnus-summary-recenter ()
   "Center point in the summary window.
@@ -9180,11 +9729,13 @@ displayed, no centering will be performed."
        window (min bottom (save-excursion 
                             (forward-line (- top)) (point)))))
       ;; Do horizontal recentering while we're at it.
-      (let ((selected (selected-window)))
-       (select-window (get-buffer-window (current-buffer) t))
-       (gnus-summary-position-point)
-       (gnus-horizontal-recenter)
-       (select-window selected)))))
+      (when (and (get-buffer-window (current-buffer) t)
+                (not (eq gnus-auto-center-summary 'vertical)))
+       (let ((selected (selected-window)))
+         (select-window (get-buffer-window (current-buffer) t))
+         (gnus-summary-position-point)
+         (gnus-horizontal-recenter)
+         (select-window selected))))))
 
 (defun gnus-horizontal-recenter ()
   "Recenter the current buffer horizontally."
@@ -9271,17 +9822,15 @@ displayed, no centering will be performed."
          (setq first (1+ (cdr read)))
        ;; `read' is a list of ranges.
        (if (/= (setq nlast (or (and (numberp (car read)) (car read))
-                               (car (car read)))) 1)
+                               (caar read))) 1)
            (setq first 1))
        (while read
          (if first
              (while (< first nlast)
                (setq unread (cons first unread))
                (setq first (1+ first))))
-         (setq first (1+ (if (atom (car read)) (car read) (cdr (car read)))))
-         (setq nlast (if (atom (car (cdr read)))
-                         (car (cdr read))
-                       (car (car (cdr read)))))
+         (setq first (1+ (if (atom (car read)) (car read) (cdar read))))
+         (setq nlast (if (atom (cadr read)) (cadr read) (caadr read)))
          (setq read (cdr read)))))
     ;; And add the last unread articles.
     (while (<= first last)
@@ -9321,9 +9870,7 @@ displayed, no centering will be performed."
             "\\<gnus-summary-mode-map>\\[gnus-summary-universal-argument]"
             ))))
         'undefined)
-       (progn
-         (message "Undefined key")
-         (ding))
+       (gnus-error 1 "Undefined key")
       (save-excursion
        (while articles
          (gnus-summary-goto-subject (setq article (pop articles)))
@@ -9345,6 +9892,8 @@ With arg, turn line truncation on iff arg is positive."
 The prefix argument ALL means to select all articles."
   (interactive "P")
   (gnus-set-global-variables)
+  (when (gnus-ephemeral-group-p gnus-newsgroup-name)
+    (error "Ephemeral groups can't be reselected"))
   (let ((current-subject (gnus-summary-article-number))
        (group gnus-newsgroup-name))
     (setq gnus-newsgroup-begin nil)
@@ -9357,7 +9906,7 @@ The prefix argument ALL means to select all articles."
       (save-excursion
        (gnus-group-get-new-news-this-group 1)))
     (gnus-group-read-group all t)
-    (gnus-summary-goto-subject current-subject)))
+    (gnus-summary-goto-subject current-subject nil t)))
 
 (defun gnus-summary-rescan-group (&optional all)
   "Exit the newsgroup, ask for new articles, and select the newsgroup."
@@ -9379,7 +9928,6 @@ The prefix argument ALL means to select all articles."
     (unless (listp (cdr gnus-newsgroup-killed))
       (setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
     (let ((headers gnus-newsgroup-headers))
-      (gnus-close-group group)
       (run-hooks 'gnus-exit-group-hook)
       (unless gnus-save-score
        (setq gnus-newsgroup-scored nil))
@@ -9412,26 +9960,33 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
         (mode major-mode)
         (buf (current-buffer)))
     (run-hooks 'gnus-summary-prepare-exit-hook)
+    ;; If we have several article buffers, we kill them at exit.
+    (unless gnus-single-article-buffer
+      (gnus-kill-buffer gnus-original-article-buffer)
+      (setq gnus-article-current nil))
     (when gnus-use-cache
       (gnus-cache-possibly-remove-articles)
       (gnus-cache-save-buffers))
     (when gnus-use-trees
       (gnus-tree-close group))
     ;; Make all changes in this group permanent.
-    (gnus-summary-update-info)
+    (unless quit-config
+      (gnus-summary-update-info))
+    (gnus-close-group group)
     ;; Make sure where I was, and go to next newsgroup.
     (set-buffer gnus-group-buffer)
-    (or quit-config
-       (progn
-         (gnus-group-jump-to-group group)
-         (gnus-group-next-unread-group 1)))
+    (unless quit-config
+      (gnus-group-jump-to-group group))
     (run-hooks 'gnus-summary-exit-hook)
+    (unless quit-config
+      (gnus-group-next-unread-group 1))
     (if temporary
        nil                             ;Nothing to do.
       ;; If we have several article buffers, we kill them at exit.
       (unless gnus-single-article-buffer
        (gnus-kill-buffer gnus-article-buffer)
-       (gnus-kill-buffer gnus-original-article-buffer))
+       (gnus-kill-buffer gnus-original-article-buffer)
+       (setq gnus-article-current nil))
       (set-buffer buf)
       (if (not gnus-kill-summary-on-exit)
          (gnus-deaden-summary)
@@ -9479,7 +10034,8 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
       ;; If we have several article buffers, we kill them at exit.
       (unless gnus-single-article-buffer
        (gnus-kill-buffer gnus-article-buffer)
-       (gnus-kill-buffer gnus-original-article-buffer))
+       (gnus-kill-buffer gnus-original-article-buffer)
+       (setq gnus-article-current nil))
       (if (not gnus-kill-summary-on-exit)
          (gnus-deaden-summary)
        (gnus-close-group group)
@@ -9488,6 +10044,8 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
        (gnus-summary-clear-local-variables)
        (when (get-buffer gnus-summary-buffer)
          (kill-buffer gnus-summary-buffer)))
+      (unless gnus-single-article-buffer
+       (setq gnus-article-current nil))
       (when gnus-use-trees
        (gnus-tree-close group))
       (when (get-buffer gnus-article-buffer)
@@ -9559,6 +10117,12 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
 
 (defun gnus-kill-or-deaden-summary (buffer)
   "Kill or deaden the summary BUFFER."
+  (when (and (buffer-name buffer)
+            (not gnus-single-article-buffer))
+    (save-excursion
+      (set-buffer buffer)
+      (gnus-kill-buffer gnus-article-buffer)
+      (gnus-kill-buffer gnus-original-article-buffer)))
   (cond (gnus-kill-summary-on-exit
         (when (and gnus-use-trees
                    (and (get-buffer buffer)
@@ -9712,10 +10276,9 @@ returned."
       (setq n (1- n)))
     (if (/= 0 n) (gnus-message 7 "No more%s articles"
                               (if unread " unread" "")))
-    (or dont-display
-       (progn
-         (gnus-summary-recenter)
-         (gnus-summary-position-point)))
+    (unless dont-display
+      (gnus-summary-recenter)
+      (gnus-summary-position-point))
     n))
 
 (defun gnus-summary-next-unread-subject (n)
@@ -9742,7 +10305,7 @@ If FORCE, also allow jumping to articles not currently shown."
     ;; We read in the article if we have to.
     (and (not data)
         force
-        (gnus-summary-insert-subject article)
+        (gnus-summary-insert-subject article (and (vectorp force) force) t)
         (setq data (gnus-data-find article)))
     (goto-char b)
     (if (not data)
@@ -9774,15 +10337,15 @@ Given a prefix, will force an `article' buffer configuration."
            (funcall gnus-summary-display-article-function article all-header)
          (gnus-article-prepare article all-header))
       (run-hooks 'gnus-select-article-hook)
+      (unless (zerop gnus-current-article)
+       (gnus-summary-goto-subject gnus-current-article))
       (gnus-summary-recenter)
-      (gnus-summary-goto-subject article)
       (when gnus-use-trees
        (gnus-possibly-generate-tree article)
        (gnus-highlight-selected-tree article))
       ;; Successfully display article.
       (gnus-article-set-window-start
-       (cdr (assq article gnus-newsgroup-bookmarks)))
-      t)))
+       (cdr (assq article gnus-newsgroup-bookmarks))))))
 
 (defun gnus-summary-select-article (&optional all-headers force pseudo article)
   "Select the current article.
@@ -9790,6 +10353,9 @@ If ALL-HEADERS is non-nil, show all header fields.  If FORCE is
 non-nil, the article will be re-fetched even if it already present in
 the article buffer.  If PSEUDO is non-nil, pseudo-articles will also
 be displayed."
+  ;; Make sure we are in the summary buffer to work around bbdb bug.
+  (unless (eq major-mode 'gnus-summary-mode)
+    (set-buffer gnus-summary-buffer))
   (let ((article (or article (gnus-summary-article-number)))
        (all-headers (not (not all-headers))) ;Must be T or NIL.
        gnus-summary-display-article-function
@@ -9808,7 +10374,8 @@ be displayed."
                           (not (equal (car gnus-article-current)
                                       gnus-newsgroup-name))))
                  (and (not gnus-single-article-buffer)
-                      (null gnus-current-article))
+                      (or (null gnus-current-article)
+                          (not (eq gnus-current-article article))))
                  force)
              ;; The requested article is different from the current article.
              (prog1
@@ -9832,58 +10399,58 @@ If SUBJECT, only articles with SUBJECT are selected.
 If BACKWARD, the previous article is selected instead of the next."
   (interactive "P")
   (gnus-set-global-variables)
-  (let (header)
-    (cond
-     ;; Is there such an article?
-     ((and (gnus-summary-search-forward unread subject backward)
-          (or (gnus-summary-display-article (gnus-summary-article-number))
-              (eq (gnus-summary-article-mark) gnus-canceled-mark)))
-      (gnus-summary-position-point))
-     ;; If not, we try the first unread, if that is wanted.
-     ((and subject
-          gnus-auto-select-same
-          (or (gnus-summary-first-unread-article)
-              (eq (gnus-summary-article-mark) gnus-canceled-mark)))
-      (gnus-summary-position-point)
-      (gnus-message 6 "Wrapped"))
-     ;; Try to get next/previous article not displayed in this group.
-     ((and gnus-auto-extend-newsgroup
-          (not unread) (not subject))
-      (gnus-summary-goto-article
-       (if backward (1- gnus-newsgroup-begin) (1+ gnus-newsgroup-end))
-       nil t))
-     ;; Go to next/previous group.
-     (t
-      (or (gnus-ephemeral-group-p gnus-newsgroup-name)
-         (gnus-summary-jump-to-group gnus-newsgroup-name))
-      (let ((cmd last-command-char)
-           (group
-            (if (eq gnus-keep-same-level 'best)
-                (gnus-summary-best-group gnus-newsgroup-name)
-              (gnus-summary-search-group backward gnus-keep-same-level))))
-       ;; For some reason, the group window gets selected.  We change
-       ;; it back.
-       (select-window (get-buffer-window (current-buffer)))
-       ;; Select next unread newsgroup automagically.
-       (cond
-        ((not gnus-auto-select-next)
-         (gnus-message 7 "No more%s articles" (if unread " unread" "")))
-        ((or (eq gnus-auto-select-next 'quietly)
-             (and (eq gnus-auto-select-next 'slightly-quietly)
-                  push)
-             (and (eq gnus-auto-select-next 'almost-quietly)
-                  (gnus-summary-last-article-p)))
-         ;; Select quietly.
-         (if (gnus-ephemeral-group-p gnus-newsgroup-name)
-             (gnus-summary-exit)
-           (gnus-message 7 "No more%s articles (%s)..."
-                         (if unread " unread" "")
-                         (if group (concat "selecting " group)
-                           "exiting"))
-           (gnus-summary-next-group nil group backward)))
-        (t
-         (gnus-summary-walk-group-buffer
-          gnus-newsgroup-name cmd unread backward))))))))
+  (cond
+   ;; Is there such an article?
+   ((and (gnus-summary-search-forward unread subject backward)
+        (or (gnus-summary-display-article (gnus-summary-article-number))
+            (eq (gnus-summary-article-mark) gnus-canceled-mark)))
+    (gnus-summary-position-point))
+   ;; If not, we try the first unread, if that is wanted.
+   ((and subject
+        gnus-auto-select-same
+        (or (gnus-summary-first-unread-article)
+            (eq (gnus-summary-article-mark) gnus-canceled-mark)))
+    (gnus-summary-position-point)
+    (gnus-message 6 "Wrapped"))
+   ;; Try to get next/previous article not displayed in this group.
+   ((and gnus-auto-extend-newsgroup
+        (not unread) (not subject))
+    (gnus-summary-goto-article
+     (if backward (1- gnus-newsgroup-begin) (1+ gnus-newsgroup-end))
+     nil t))
+   ;; Go to next/previous group.
+   (t
+    (or (gnus-ephemeral-group-p gnus-newsgroup-name)
+       (gnus-summary-jump-to-group gnus-newsgroup-name))
+    (let ((cmd last-command-char)
+         (group
+          (if (eq gnus-keep-same-level 'best)
+              (gnus-summary-best-group gnus-newsgroup-name)
+            (gnus-summary-search-group backward gnus-keep-same-level))))
+      ;; For some reason, the group window gets selected.  We change
+      ;; it back.
+      (select-window (get-buffer-window (current-buffer)))
+      ;; Select next unread newsgroup automagically.
+      (cond
+       ((or (not gnus-auto-select-next)
+           (not cmd))
+       (gnus-message 7 "No more%s articles" (if unread " unread" "")))
+       ((or (eq gnus-auto-select-next 'quietly)
+           (and (eq gnus-auto-select-next 'slightly-quietly)
+                push)
+           (and (eq gnus-auto-select-next 'almost-quietly)
+                (gnus-summary-last-article-p)))
+       ;; Select quietly.
+       (if (gnus-ephemeral-group-p gnus-newsgroup-name)
+           (gnus-summary-exit)
+         (gnus-message 7 "No more%s articles (%s)..."
+                       (if unread " unread" "")
+                       (if group (concat "selecting " group)
+                         "exiting"))
+         (gnus-summary-next-group nil group backward)))
+       (t
+       (gnus-summary-walk-group-buffer
+        gnus-newsgroup-name cmd unread backward)))))))
 
 (defun gnus-summary-walk-group-buffer (from-group cmd unread backward)
   (let ((keystrokes '((?\C-n (gnus-group-next-unread-group 1))
@@ -9916,7 +10483,7 @@ If BACKWARD, the previous article is selected instead of the next."
          (switch-to-buffer gnus-group-buffer)
          (and group
               (gnus-group-jump-to-group group))
-         (eval (car (cdr (assq key keystrokes))))
+         (eval (cadr (assq key keystrokes)))
          (setq group (gnus-group-group-name))
          (switch-to-buffer obuf))
        (setq ended nil))
@@ -9965,24 +10532,29 @@ article."
   (let ((article (gnus-summary-article-number))
        (endp nil))
     (gnus-configure-windows 'article)
-    (if (or (null gnus-current-article)
-           (null gnus-article-current)
-           (/= article (cdr gnus-article-current))
-           (not (equal (car gnus-article-current) gnus-newsgroup-name)))
-       ;; Selected subject is different from current article's.
-       (gnus-summary-display-article article)
-      (gnus-eval-in-buffer-window
-       gnus-article-buffer
-       (setq endp (gnus-article-next-page lines)))
-      (if endp
-         (cond (circular
-                (gnus-summary-beginning-of-article))
-               (lines
-                (gnus-message 3 "End of message"))
-               ((null lines)
-                (if (eq gnus-summary-goto-unread 'always)
-                    (gnus-summary-next-article)
-                  (gnus-summary-next-unread-article))))))
+    (if (eq (cdr (assq article gnus-newsgroup-reads)) gnus-canceled-mark)
+       (if (and (eq gnus-summary-goto-unread 'never)
+                (not (gnus-summary-last-article-p article)))
+           (gnus-summary-next-article)
+         (gnus-summary-next-unread-article))
+      (if (or (null gnus-current-article)
+             (null gnus-article-current)
+             (/= article (cdr gnus-article-current))
+             (not (equal (car gnus-article-current) gnus-newsgroup-name)))
+         ;; Selected subject is different from current article's.
+         (gnus-summary-display-article article)
+       (gnus-eval-in-buffer-window gnus-article-buffer
+         (setq endp (gnus-article-next-page lines)))
+       (if endp
+           (cond (circular
+                  (gnus-summary-beginning-of-article))
+                 (lines
+                  (gnus-message 3 "End of message"))
+                 ((null lines)
+                  (if (and (eq gnus-summary-goto-unread 'never)
+                           (not (gnus-summary-last-article-p article)))
+                      (gnus-summary-next-article)
+                    (gnus-summary-next-unread-article)))))))
     (gnus-summary-recenter)
     (gnus-summary-position-point)))
 
@@ -10001,7 +10573,7 @@ Argument LINES specifies lines to be scrolled down."
        (gnus-summary-display-article article)
       (gnus-summary-recenter)
       (gnus-eval-in-buffer-window gnus-article-buffer
-                                 (gnus-article-prev-page lines))))
+       (gnus-article-prev-page lines))))
   (gnus-summary-position-point))
 
 (defun gnus-summary-scroll-up (lines)
@@ -10010,14 +10582,14 @@ Argument LINES specifies lines to be scrolled up (or down if negative)."
   (interactive "p")
   (gnus-set-global-variables)
   (gnus-configure-windows 'article)
+  (gnus-summary-show-thread)
   (when (eq (gnus-summary-select-article nil nil 'pseudo) 'old)
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (cond ((> lines 0)
-           (if (gnus-article-next-page lines)
-               (gnus-message 3 "End of message")))
-          ((< lines 0)
-           (gnus-article-prev-page (- lines))))))
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (cond ((> lines 0)
+            (if (gnus-article-next-page lines)
+                (gnus-message 3 "End of message")))
+           ((< lines 0)
+            (gnus-article-prev-page (- lines))))))
   (gnus-summary-recenter)
   (gnus-summary-position-point))
 
@@ -10073,10 +10645,11 @@ Return nil if there are no unread articles."
           (setq best score
                 article (gnus-data-number (car data))))
       (setq data (cdr data)))
-    (if article
-       (gnus-summary-goto-article article)
-      (error "No unread articles"))
-    (gnus-summary-position-point)))
+    (prog1
+       (if article
+           (gnus-summary-goto-article article)
+         (error "No unread articles"))
+      (gnus-summary-position-point))))
 
 (defun gnus-summary-last-subject ()
   "Go to the last displayed subject line in the group."
@@ -10157,7 +10730,8 @@ If given a prefix, remove all limits."
     (setq header "subject"))
   (when (not (equal "" subject))
     (prog1
-       (let ((articles (gnus-summary-find-matching "subject" subject 'all)))
+       (let ((articles (gnus-summary-find-matching
+                        (or header "subject") subject 'all)))
          (or articles (error "Found no matches for \"%s\"" subject))
          (gnus-summary-limit articles))
       (gnus-summary-position-point))))
@@ -10249,16 +10823,22 @@ Returns how many articles were removed."
   "Hide all dormant articles that have no children."
   (interactive)
   (gnus-set-global-variables)
-  (let ((data gnus-newsgroup-data)
-       articles)
+  (let ((data (gnus-data-list t))
+       articles d children)
     ;; Find all articles that are either not dormant or have
     ;; children.
-    (while data
-      (and (or (not (= (gnus-data-mark (car data)) gnus-dormant-mark))
-              (gnus-article-parent-p (gnus-data-number (car data))))
-          (setq articles (cons (gnus-data-number (car data))
-                               articles)))
-      (setq data (cdr data)))
+    (while (setq d (pop data))
+      (when (or (not (= (gnus-data-mark d) gnus-dormant-mark))
+               (and (setq children 
+                          (gnus-article-children (gnus-data-number d)))
+                    (let (found)
+                      (while children
+                        (when (memq (car children) articles)
+                          (setq children nil
+                                found t))
+                        (pop children))
+                      found)))
+       (push (gnus-data-number d) articles)))
     ;; Do the limiting.
     (prog1
        (gnus-summary-limit articles)
@@ -10288,7 +10868,6 @@ If ALL, mark even excluded ticked and dormants as read."
                    (memq article gnus-newsgroup-marked))
          (push (cons article gnus-catchup-mark) gnus-newsgroup-reads))))))
 
-
 (defun gnus-summary-limit (articles &optional pop)
   (if pop
       ;; We pop the previous limit off the stack and use that.
@@ -10330,17 +10909,27 @@ If ALL, mark even excluded ticked and dormants as read."
     ;; buffer as a result of the new limit.
     (- total (length gnus-newsgroup-data))))
 
+(defsubst gnus-invisible-cut-children (threads)
+  (let ((num 0))
+    (while threads
+      (when (memq (mail-header-number (caar threads)) gnus-newsgroup-limit)
+       (incf num))
+      (pop threads))
+    (< num 2)))
+
 (defsubst gnus-cut-thread (thread)
   "Go forwards in the thread until we find an article that we want to display."
-  (if (eq gnus-fetch-old-headers 'some)
-      (while (and thread
-                 (memq (mail-header-number (car thread)) 
-                       gnus-newsgroup-ancient)
-                 (<= (length (cdr thread)) 1))
-       (setq thread (cadr thread)))
-    (while (and thread
-               (memq (mail-header-number (car thread)) gnus-newsgroup-sparse)
-               (= (length (cdr thread)) 1))
+  (when (or (eq gnus-fetch-old-headers 'some)
+           (eq gnus-build-sparse-threads 'some)
+           (eq gnus-build-sparse-threads 'more))
+    ;; Deal with old-fetched headers and sparse threads.
+    (while (and
+           thread
+           (or
+            (memq (mail-header-number (car thread)) gnus-newsgroup-sparse)
+            (memq (mail-header-number (car thread)) gnus-newsgroup-ancient))
+           (or (<= (length (cdr thread)) 1)
+               (gnus-invisible-cut-children (cdr thread))))
       (setq thread (cadr thread))))
   thread)
 
@@ -10353,7 +10942,8 @@ If ALL, mark even excluded ticked and dormants as read."
       (while th
        (setcar th (gnus-cut-thread (car th)))
        (setq th (cdr th)))))
-  threads)
+  ;; Remove nixed out threads.
+  (delq nil threads))
 
 (defun gnus-summary-initial-limit (&optional show-if-empty)
   "Figure out what the initial limit is supposed to be on group entry.
@@ -10366,7 +10956,8 @@ fetch-old-headers verbiage, and so on."
               (null gnus-summary-expunge-below)
               (not (eq gnus-build-sparse-threads 'some))
               (not (eq gnus-build-sparse-threads 'more))
-              (null gnus-thread-expunge-below)))
+              (null gnus-thread-expunge-below)
+              (not gnus-use-nocem)))
       () ; Do nothing.
     (push gnus-newsgroup-limit gnus-newsgroup-limits)
     (setq gnus-newsgroup-limit nil)
@@ -10410,7 +11001,7 @@ fetch-old-headers verbiage, and so on."
           ;; children, then this article isn't visible.
           (and (memq number gnus-newsgroup-dormant)
                (= children 0))
-          ;; If this is "fetch-old-headered" and there is only one
+          ;; If this is "fetch-old-headered" and there is only one
           ;; visible child (or less), then we don't want this article.
           (and (eq gnus-fetch-old-headers 'some)
                (memq number gnus-newsgroup-ancient)
@@ -10439,7 +11030,9 @@ fetch-old-headers verbiage, and so on."
                   (push number gnus-newsgroup-expirable)
                 (push (cons number gnus-low-score-mark)
                       gnus-newsgroup-reads)))
-            t))
+            t)
+          (and gnus-use-nocem
+               (gnus-nocem-unwanted-article-p (mail-header-id (car thread)))))
          ;; Nope, invisible article.
          0
        ;; Ok, this article is to be visible, so we add it to the limit
@@ -10486,12 +11079,12 @@ The difference between N and the number of articles fetched is returned."
                     (set-buffer gnus-original-article-buffer)
                     (nnheader-narrow-to-headers)
                     (prog1
-                        (mail-fetch-field "references")
+                        (message-fetch-field "references")
                       (widen)))
                 ;; It's not the current article, so we take a bet on
                 ;; the value we got from the server.
                 (mail-header-references header))))
-        (if ref
+        (if (setq ref (or ref (mail-header-references header)))
             (or (gnus-summary-refer-article (gnus-parent-id ref))
                 (gnus-message 1 "Couldn't find parent"))
           (gnus-message 1 "No references in article %d"
@@ -10531,16 +11124,25 @@ Return how many articles were fetched."
       (setq message-id (concat "<" message-id)))
     (unless (string-match ">$" message-id)
       (setq message-id (concat message-id ">")))
-    (let ((header (car (gnus-gethash (downcase message-id)
-                                    gnus-newsgroup-dependencies))))
+    (let* ((header (gnus-id-to-header message-id))
+          (sparse (and header
+                       (memq (mail-header-number header)
+                             gnus-newsgroup-sparse))))
       (if header
-         ;; The article is present in the buffer, to we just go to it.
-         (gnus-summary-goto-article (mail-header-number header) nil t)
+         (prog1
+             ;; The article is present in the buffer, to we just go to it.
+             (gnus-summary-goto-article 
+              (mail-header-number header) nil header)
+           (when sparse
+             (gnus-summary-update-article (mail-header-number header))))
        ;; We fetch the article
-       (let ((gnus-override-method gnus-refer-article-method)
+       (let ((gnus-override-method 
+              (and (gnus-news-group-p gnus-newsgroup-name)
+                   gnus-refer-article-method))
              number)
          ;; Start the special refer-article method, if necessary.
-         (when gnus-refer-article-method
+         (when (and gnus-refer-article-method
+                    (gnus-news-group-p gnus-newsgroup-name))
            (gnus-check-server gnus-refer-article-method))
          ;; Fetch the header, and display the article.
          (if (setq number (gnus-summary-insert-subject message-id))
@@ -10567,7 +11169,7 @@ Return how many articles were fetched."
        (goto-char (point-min))
        (or (search-forward "\n\n" nil t) (point)))
       (goto-char (point-min))
-      (delete-matching-lines "^\\(Path\\):")
+      (delete-matching-lines "^\\(Path\\):\\|^From ")
       (widen))
     (unwind-protect
        (if (gnus-group-read-ephemeral-group
@@ -10575,8 +11177,8 @@ Return how many articles were fetched."
                                 ,(get-buffer dig))
                          (nndoc-article-type ,(if force 'digest 'guess))) t)
            ;; Make all postings to this group go to the parent group.
-           (setcdr (nthcdr 4 (gnus-get-info name))
-                   (list (list (cons 'to-group ogroup))))
+           (nconc (gnus-info-params (gnus-get-info name))
+                  (list (cons 'to-group ogroup)))
          ;; Couldn't select this doc group.
          (switch-to-buffer buf)
          (gnus-set-global-variables)
@@ -10591,10 +11193,9 @@ If REGEXP-P (the prefix) is non-nil, do regexp isearch."
   (gnus-set-global-variables)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
-  (gnus-eval-in-buffer-window
-   gnus-article-buffer
-   (goto-char (point-min))
-   (isearch-forward regexp-p)))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (goto-char (point-min))
+    (isearch-forward regexp-p)))
 
 (defun gnus-summary-search-article-forward (regexp &optional backward)
   "Search for an article containing REGEXP forward.
@@ -10611,9 +11212,7 @@ If BACKWARD, search backward instead."
   (if (string-equal regexp "")
       (setq regexp (or gnus-last-search-regexp ""))
     (setq gnus-last-search-regexp regexp))
-  (if (gnus-summary-search-article regexp backward)
-      (gnus-article-set-window-start
-       (cdr (assq (gnus-summary-article-number) gnus-newsgroup-bookmarks)))
+  (unless (gnus-summary-search-article regexp backward)
     (error "Search failed: \"%s\"" regexp)))
 
 (defun gnus-summary-search-article-backward (regexp)
@@ -10629,46 +11228,52 @@ If BACKWARD, search backward instead."
 (defun gnus-summary-search-article (regexp &optional backward)
   "Search for an article containing REGEXP.
 Optional argument BACKWARD means do search for backward.
-gnus-select-article-hook is not called during the search."
+`gnus-select-article-hook' is not called during the search."
   (let ((gnus-select-article-hook nil) ;Disable hook.
+       (gnus-article-display-hook nil)
        (gnus-mark-article-hook nil)    ;Inhibit marking as read.
        (re-search
         (if backward
-            (function re-search-backward) (function re-search-forward)))
-       (found nil)
-       (last nil))
-    ;; Hidden thread subtrees must be searched for ,too.
-    (gnus-summary-show-all-threads)
-    ;; First of all, search current article.
-    ;; We don't want to read article again from NNTP server nor reset
-    ;; current point.
-    (gnus-summary-select-article)
-    (gnus-message 9 "Searching article: %d..." gnus-current-article)
-    (setq last gnus-current-article)
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (save-restriction
-       (widen)
-       ;; Begin search from current point.
-       (setq found (funcall re-search regexp nil t))))
-    ;; Then search next articles.
-    (while (and (not found)
-               (gnus-summary-display-article
-                (if backward (gnus-summary-find-prev)
-                  (gnus-summary-find-next))))
-      (gnus-message 9 "Searching article: %d..." gnus-current-article)
-      (gnus-eval-in-buffer-window
-       gnus-article-buffer
-       (save-restriction
-        (widen)
-        (goto-char (if backward (point-max) (point-min)))
-        (setq found (funcall re-search regexp nil t)))))
-    (message "")
-    ;; Adjust article pointer.
-    (or (eq last gnus-current-article)
-       (setq gnus-last-article last))
-    ;; Return T if found such article.
-    found))
+            're-search-backward 're-search-forward))
+       (sum (current-buffer))
+       (found nil))
+    (gnus-save-hidden-threads
+      (gnus-summary-select-article)
+      (set-buffer gnus-article-buffer)
+      (when backward
+       (forward-line -1))
+      (while (not found)
+       (gnus-message 7 "Searching article: %d..." (cdr gnus-article-current))
+       (if (if backward
+               (re-search-backward regexp nil t)
+             (re-search-forward regexp nil t))
+           ;; We found the regexp.
+           (progn
+             (setq found 'found)
+             (beginning-of-line)
+             (set-window-start
+              (get-buffer-window (current-buffer))
+              (point))
+             (forward-line 1)
+             (set-buffer sum))
+         ;; We didn't find it, so we go to the next article.
+         (set-buffer sum)
+         (if (not (if backward (gnus-summary-find-prev)
+                    (gnus-summary-find-next)))
+             ;; No more articles.
+             (setq found t)
+           ;; Select the next article and adjust point.
+           (gnus-summary-select-article)
+           (set-buffer gnus-article-buffer)
+           (widen)
+           (goto-char (if backward (point-max) (point-min))))))
+      (gnus-message 7 ""))
+    ;; Return whether we found the regexp.
+    (when (eq found 'found)
+      (gnus-summary-show-thread)
+      (gnus-summary-goto-subject gnus-current-article)
+      (gnus-summary-position-point)
+      t)))
 
 (defun gnus-summary-find-matching (header regexp &optional backward unread
                                          not-case-fold)
@@ -10706,11 +11311,13 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
            "Header name: "
            (mapcar (lambda (string) (list string))
                    '("Number" "Subject" "From" "Lines" "Date"
-                     "Message-ID" "Xref" "References"))
+                     "Message-ID" "Xref" "References" "Body"))
            nil 'require-match))
         (read-string "Regexp: ")
         (read-key-sequence "Command: ")
         current-prefix-arg))
+  (when (equal header "Body")
+    (setq header ""))
   (gnus-set-global-variables)
   ;; Hidden thread subtrees must be searched as well.
   (gnus-summary-show-all-threads)
@@ -10730,11 +11337,10 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
   (gnus-set-global-variables)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
-  (gnus-eval-in-buffer-window
-   gnus-article-buffer
-   (widen)
-   (goto-char (point-min))
-   (and gnus-break-pages (gnus-narrow-to-page))))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (widen)
+    (goto-char (point-min))
+    (and gnus-break-pages (gnus-narrow-to-page))))
 
 (defun gnus-summary-end-of-article ()
   "Scroll to the end of the article."
@@ -10742,12 +11348,11 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
   (gnus-set-global-variables)
   (gnus-summary-select-article)
   (gnus-configure-windows 'article)
-  (gnus-eval-in-buffer-window
-   gnus-article-buffer
-   (widen)
-   (goto-char (point-max))
-   (recenter -3)
-   (and gnus-break-pages (gnus-narrow-to-page))))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (widen)
+    (goto-char (point-max))
+    (recenter -3)
+    (and gnus-break-pages (gnus-narrow-to-page))))
 
 (defun gnus-summary-show-article (&optional arg)
   "Force re-fetching of the current article.
@@ -10762,8 +11367,10 @@ article massaging functions being run."
     (let ((gnus-have-all-headers t)
          gnus-article-display-hook
          gnus-article-prepare-hook
+         gnus-break-pages
          gnus-visual)
       (gnus-summary-select-article nil 'force)))
+  (gnus-summary-goto-subject gnus-current-article)
 ;  (gnus-configure-windows 'article)
   (gnus-summary-position-point))
 
@@ -10833,20 +11440,21 @@ forward."
   (gnus-set-global-variables)
   (gnus-summary-select-article)
   (let ((mail-header-separator ""))
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (save-restriction
-       (widen)
-       (let ((start (window-start)))
-        (news-caesar-buffer-body arg)
-        (set-window-start (get-buffer-window (current-buffer)) start))))))
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (save-restriction
+       (widen)
+       (let ((start (window-start))
+             buffer-read-only)
+         (message-caesar-buffer-body arg)
+         (set-window-start (get-buffer-window (current-buffer)) start))))))
 
 (defun gnus-summary-stop-page-breaking ()
   "Stop page breaking in the current article."
   (interactive)
   (gnus-set-global-variables)
   (gnus-summary-select-article)
-  (gnus-eval-in-buffer-window gnus-article-buffer (widen)))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (widen)))
 
 (defun gnus-summary-move-article (&optional n to-newsgroup select-method action)
   "Move the current article to a different newsgroup.
@@ -10855,7 +11463,7 @@ If N is a negative number, move the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 move those articles instead.
 If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
-If SELECT-METHOD is symbol, do not move to a specific newsgroup, but
+If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
 re-spool using this method.
 
 For this function to work, both the current newsgroup and the
@@ -10875,12 +11483,12 @@ and `request-accept' functions."
         (error "The current group does not support article editing")))
   (let ((articles (gnus-summary-work-articles n))
        (prefix (gnus-group-real-prefix gnus-newsgroup-name))
-       (names '((move "move" "Moving")
-                (copy "copy" "Copying")
-                (crosspost "crosspost" "Crossposting")))
+       (names '((move "Move" "Moving")
+                (copy "Copy" "Copying")
+                (crosspost "Crosspost" "Crossposting")))
        (copy-buf (save-excursion
                    (nnheader-set-temp-buffer " *copy article*")))
-       art-group to-method new-xref article)
+       art-group to-method new-xref article to-groups)
     (unless (assq action names)
       (error "Unknown action %s" action))
     ;; Read the newsgroup name.
@@ -10889,12 +11497,11 @@ and `request-accept' functions."
       (setq to-newsgroup
            (gnus-read-move-group-name
             (cadr (assq action names))
-            gnus-current-move-group articles prefix))
+            (symbol-value (intern (format "gnus-current-%s-group" action)))
+            articles prefix))
       (set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
-    (setq to-method (if select-method (list select-method "")
-                     (gnus-find-method-for-group to-newsgroup)))
-    ;;(when (equal to-newsgroup gnus-newsgroup-name)
-    ;;(error "Can't %s to the same group you're already in" action))
+    (setq to-method (or select-method 
+                       (gnus-group-name-to-method to-newsgroup)))
     ;; Check the method we are to move this article to...
     (or (gnus-check-backend-function 'request-accept-article (car to-method))
        (error "%s does not support article copying" (car to-method)))
@@ -10902,7 +11509,7 @@ and `request-accept' functions."
        (error "Can't open server %s" (car to-method)))
     (gnus-message 6 "%s to %s: %s..."
                  (caddr (assq action names))
-                 (or select-method to-newsgroup) articles)
+                 (or (car select-method) to-newsgroup) articles)
     (while articles
       (setq article (pop articles))
       (setq
@@ -10911,24 +11518,21 @@ and `request-accept' functions."
        ;; Move the article.
        ((eq action 'move)
         (gnus-request-move-article
-         article               ; Article to move
-         gnus-newsgroup-name   ; From newsgrouo
+         article                       ; Article to move
+         gnus-newsgroup-name           ; From newsgrouo
          (nth 1 (gnus-find-method-for-group
                  gnus-newsgroup-name)) ; Server
          (list 'gnus-request-accept-article
-               (if select-method
-                   (list 'quote select-method)
-                 to-newsgroup)
-               (not articles)) ; Accept form
-         (not articles)))      ; Only save nov last time
+               to-newsgroup (list 'quote select-method)
+               (not articles))         ; Accept form
+         (not articles)))              ; Only save nov last time
        ;; Copy the article.
        ((eq action 'copy)
         (save-excursion
           (set-buffer copy-buf)
           (gnus-request-article-this-buffer article gnus-newsgroup-name)
           (gnus-request-accept-article
-           (if select-method select-method to-newsgroup)
-           (not articles))))
+           to-newsgroup select-method (not articles))))
        ;; Crosspost the article.
        ((eq action 'crosspost)
         (let ((xref (mail-header-xref (gnus-summary-article-header article))))
@@ -10944,8 +11548,7 @@ and `request-accept' functions."
             (gnus-request-article-this-buffer article gnus-newsgroup-name)
             (nnheader-replace-header "xref" new-xref)
             (gnus-request-accept-article
-             (if select-method select-method to-newsgroup)
-             (not articles)))))))
+             to-newsgroup select-method (not articles)))))))
       (if (not art-group)
          (gnus-message 1 "Couldn't %s article %s"
                        (cadr (assq action names)) article)
@@ -10955,13 +11558,17 @@ and `request-accept' functions."
                 (gnus-gethash
                  (gnus-group-prefixed-name
                   (car art-group)
-                  (if select-method (list select-method "")
-                    (gnus-find-method-for-group to-newsgroup)))
+                  (or select-method 
+                      (gnus-find-method-for-group to-newsgroup)))
                  gnus-newsrc-hashtb)))
-              (info (nth 2 entry)))
+              (info (nth 2 entry))
+              (to-group (gnus-info-group info)))
          ;; Update the group that has been moved to.
          (when (and info
                     (memq action '(move copy)))
+           (unless (member to-group to-groups)
+             (push to-group to-groups))
+
            (unless (memq article gnus-newsgroup-unreads)
              (gnus-info-set-read
               info (gnus-add-to-range (gnus-info-read info)
@@ -10974,7 +11581,7 @@ and `request-accept' functions."
              ;; See whether the article is to be put in the cache.
              (when gnus-use-cache
                (gnus-cache-possibly-enter-article
-                (gnus-info-group info) to-article
+                to-group to-article
                 (let ((header (copy-sequence
                                (gnus-summary-article-header article))))
                   (mail-header-set-number header to-article)
@@ -10983,14 +11590,22 @@ and `request-accept' functions."
                 (memq article gnus-newsgroup-dormant)
                 (memq article gnus-newsgroup-unreads)))
 
-               (while marks
-                 (when (memq article (symbol-value
-                                      (intern (format "gnus-newsgroup-%s"
-                                                      (caar marks)))))
-                   (gnus-add-marked-articles
-                    (gnus-info-group info) (caar marks)
-                    (list to-article) info))
-                 (setq marks (cdr marks)))))
+             (while marks
+               (when (memq article (symbol-value
+                                    (intern (format "gnus-newsgroup-%s"
+                                                    (caar marks)))))
+                 ;; If the other group is the same as this group,
+                 ;; then we have to add the mark to the list.
+                 (when (equal to-group gnus-newsgroup-name)
+                   (set (intern (format "gnus-newsgroup-%s" (caar marks)))
+                        (cons to-article
+                              (symbol-value
+                               (intern (format "gnus-newsgroup-%s"
+                                               (caar marks)))))))
+                 ;; Copy mark to other group.
+                 (gnus-add-marked-articles
+                  to-group (cdar marks) (list to-article) info))
+               (setq marks (cdr marks)))))
 
          ;; Update the Xref header in this article to point to
          ;; the new crossposted article we have just created.
@@ -11006,25 +11621,35 @@ and `request-accept' functions."
               article gnus-newsgroup-name (current-buffer)))))
 
        (gnus-summary-goto-subject article)
-       (gnus-summary-mark-article article gnus-canceled-mark))
+       (when (eq action 'move)
+         (gnus-summary-mark-article article gnus-canceled-mark)))
       (gnus-summary-remove-process-mark article))
+    ;; Re-activate all groups that have been moved to.
+    (while to-groups
+      (gnus-activate-group (pop to-groups)))
+    
     (gnus-kill-buffer copy-buf)
+    (gnus-summary-position-point)
     (gnus-set-mode-line 'summary)))
 
 (defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
   "Move the current article to a different newsgroup.
 If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
-If SELECT-METHOD is symbol, do not move to a specific newsgroup, but
+If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
 re-spool using this method."
   (interactive "P")
-  (gnus-summary-move-article n nil nil 'copy))
+  (gnus-summary-move-article n nil select-method 'copy))
 
 (defun gnus-summary-crosspost-article (&optional n)
   "Crosspost the current article to some other group."
   (interactive "P")
   (gnus-summary-move-article n nil nil 'crosspost))
 
-(defun gnus-summary-respool-article (&optional n respool-method)
+(defvar gnus-summary-respool-default-method nil
+  "Default method for respooling an article.  
+If nil, use to the current newsgroup method.")
+
+(defun gnus-summary-respool-article (&optional n method)
   "Respool the current article.
 The article will be squeezed through the mail spooling process again,
 which means that it will be put in some mail newsgroup or other
@@ -11038,22 +11663,35 @@ Respooling can be done both from mail groups and \"real\" newsgroups.
 In the former case, the articles in question will be moved from the
 current group into whatever groups they are destined to.  In the
 latter case, they will be copied into the relevant groups."
-  (interactive "P")
+  (interactive 
+   (list current-prefix-arg
+        (let* ((methods (gnus-methods-using 'respool))
+               (methname
+                (symbol-name (or gnus-summary-respool-default-method
+                                 (car (gnus-find-method-for-group
+                                       gnus-newsgroup-name)))))
+               (method
+                (gnus-completing-read 
+                 methname "What backend do you want to use when respooling?"
+                 methods nil t nil 'gnus-method-history))
+               ms)
+          (cond
+           ((zerop (length (setq ms (gnus-servers-using-backend method))))
+            (list (intern method) ""))
+           ((= 1 (length ms))
+            (car ms))
+           (t
+            (cdr (completing-read 
+                  "Server name: "
+                  (mapcar (lambda (m) (cons (cadr m) m)) ms) nil t)))))))
   (gnus-set-global-variables)
-  (let ((respool-methods (gnus-methods-using 'respool))
-       (methname
-        (symbol-name (car (gnus-find-method-for-group gnus-newsgroup-name)))))
-    (or respool-method
-       (setq respool-method
-             (completing-read
-              "What method do you want to use when respooling? "
-              respool-methods nil t methname)))
-    (or (string= respool-method "")
-       (if (assoc (symbol-name
-                   (car (gnus-find-method-for-group gnus-newsgroup-name)))
-                  respool-methods)
-           (gnus-summary-move-article n nil (intern respool-method))
-         (gnus-summary-copy-article n nil (intern respool-method))))))
+  (unless method
+    (error "No method given for respooling"))
+  (if (assoc (symbol-name
+             (car (gnus-find-method-for-group gnus-newsgroup-name)))
+            (gnus-methods-using 'respool))
+      (gnus-summary-move-article n nil method)
+    (gnus-summary-copy-article n nil method)))
 
 (defun gnus-summary-import-article (file)
   "Import a random file into a mail newsgroup."
@@ -11083,13 +11721,13 @@ latter case, they will be copied into the relevant groups."
                          (current-time-string (nth 5 atts))
                          (current-time-zone now)
                          (current-time-zone now)) "\n"
-               "Message-ID: " (gnus-inews-message-id) "\n"
+               "Message-ID: " (message-make-message-id) "\n"
                "Lines: " (int-to-string lines) "\n"
                "Chars: " (int-to-string (nth 7 atts)) "\n\n"))
-      (gnus-request-accept-article group t)
+      (gnus-request-accept-article group nil t)
       (kill-buffer (current-buffer)))))
 
-(defun gnus-summary-expire-articles ()
+(defun gnus-summary-expire-articles (&optional now)
   "Expire all articles that are marked as expirable in the current group."
   (interactive)
   (gnus-set-global-variables)
@@ -11101,8 +11739,9 @@ latter case, they will be copied into the relevant groups."
                          (gnus-list-of-read-articles gnus-newsgroup-name)
                        (setq gnus-newsgroup-expirable
                              (sort gnus-newsgroup-expirable '<))))
-          (expiry-wait (gnus-group-get-parameter
-                        gnus-newsgroup-name 'expiry-wait))
+          (expiry-wait (if now 'immediate
+                         (gnus-group-get-parameter
+                          gnus-newsgroup-name 'expiry-wait)))
           es)
       (when expirable
        ;; There are expirable articles in this group, so we run them
@@ -11137,11 +11776,9 @@ deleted forever, right now."
   (gnus-set-global-variables)
   (or gnus-expert-user
       (gnus-y-or-n-p
-       "Are you really, really, really sure you want to expunge? ")
+       "Are you really, really, really sure you want to delete all these messages? ")
       (error "Phew!"))
-  (let ((nnmail-expiry-wait 'immediate)
-       (nnmail-expiry-wait-function nil))
-    (gnus-summary-expire-articles)))
+  (gnus-summary-expire-articles t))
 
 ;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
 (defun gnus-summary-delete-article (&optional n)
@@ -11163,7 +11800,8 @@ delete these instead."
     (if (and gnus-novice-user
             (not (gnus-y-or-n-p
                   (format "Do you really want to delete %s forever? "
-                          (if (> (length articles) 1) "these articles"
+                          (if (> (length articles) 1) 
+                              (format "these %s articles" (length articles))
                             "this article")))))
        ()
       ;; Delete the articles.
@@ -11211,10 +11849,9 @@ groups."
   (if (gnus-group-read-only-p)
       (progn
        (gnus-summary-edit-article-postpone)
-       (gnus-message
-        1 "The current newsgroup does not support article editing.")
-       (ding))
-    (let ((buf (buffer-substring-no-properties (point-min) (point-max))))
+       (gnus-error
+        1 "The current newsgroup does not support article editing."))
+    (let ((buf (format "%s" (buffer-string))))
       (erase-buffer)
       (insert buf)
       (if (not (gnus-request-replace-article
@@ -11226,7 +11863,19 @@ groups."
        (setq buffer-read-only t)
        (buffer-disable-undo (current-buffer))
        (gnus-configure-windows 'summary)
-       (gnus-summary-update-article (cdr gnus-article-current)))
+       (gnus-summary-update-article (cdr gnus-article-current))
+       (when gnus-use-cache
+         (gnus-cache-update-article    
+          (car gnus-article-current) (cdr gnus-article-current)))
+       (when gnus-keep-backlog
+         (gnus-backlog-remove-article 
+          (car gnus-article-current) (cdr gnus-article-current))))
+      (save-excursion
+       (when (get-buffer gnus-original-article-buffer)
+         (set-buffer gnus-original-article-buffer)
+         (setq gnus-original-article nil)))
+      (setq gnus-article-current nil
+           gnus-current-article nil)
       (run-hooks 'gnus-article-display-hook)
       (and (gnus-visual-p 'summary-highlight 'highlight)
           (run-hooks 'gnus-visual-mark-article-hook)))))
@@ -11256,41 +11905,6 @@ groups."
       (pp-eval-expression
        (list 'quote (mapcar 'car (nnmail-article-group 'identity)))))))
 
-;; Summary score commands.
-
-;; Suggested by boubaker@cenatls.cena.dgac.fr.
-
-(defun gnus-summary-raise-score (n)
-  "Raise the score of the current article by N."
-  (interactive "p")
-  (gnus-set-global-variables)
-  (gnus-summary-set-score (+ (gnus-summary-article-score) n)))
-
-(defun gnus-summary-set-score (n)
-  "Set the score of the current article to N."
-  (interactive "p")
-  (gnus-set-global-variables)
-  (save-excursion
-    (gnus-summary-show-thread)
-    (let ((buffer-read-only nil))
-      ;; Set score.
-      (gnus-summary-update-mark
-       (if (= n (or gnus-summary-default-score 0)) ? 
-        (if (< n (or gnus-summary-default-score 0))
-            gnus-score-below-mark gnus-score-over-mark)) 'score))
-    (let* ((article (gnus-summary-article-number))
-          (score (assq article gnus-newsgroup-scored)))
-      (if score (setcdr score n)
-       (setq gnus-newsgroup-scored
-             (cons (cons article n) gnus-newsgroup-scored))))
-    (gnus-summary-update-line)))
-
-(defun gnus-summary-current-score ()
-  "Return the score of the current article."
-  (interactive)
-  (gnus-set-global-variables)
-  (message "%s" (gnus-summary-article-score)))
-
 ;; Summary marking commands.
 
 (defun gnus-summary-kill-same-subject-and-select (&optional unmark)
@@ -11492,9 +12106,7 @@ the actual number of articles marked is returned."
 
 (defun gnus-summary-mark-forward (n &optional mark no-expire)
   "Mark N articles as read forwards.
-If N is negative, mark backwards instead.
-Mark with MARK.         If MARK is ? , ?! or ??, articles will be
-marked as unread.
+If N is negative, mark backwards instead.  Mark with MARK, ?r by default.
 The difference between N and the actual number of articles marked is
 returned."
   (interactive "p")
@@ -11548,32 +12160,34 @@ returned."
 (defun gnus-summary-mark-article-as-unread (mark)
   "Mark the current article quickly as unread with MARK."
   (let ((article (gnus-summary-article-number)))
-    (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
-    (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
-    (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
-    (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
-    (cond ((= mark gnus-ticked-mark)
-          (push article gnus-newsgroup-marked))
-         ((= mark gnus-dormant-mark)
-          (push article gnus-newsgroup-dormant))
-         (t
-          (push article gnus-newsgroup-unreads)))
-    (setq gnus-newsgroup-reads
-         (delq (assq article gnus-newsgroup-reads)
-               gnus-newsgroup-reads))
-
-    ;; See whether the article is to be put in the cache.
-    (and gnus-use-cache
-        (vectorp (gnus-summary-article-header article))
-        (save-excursion
-          (gnus-cache-possibly-enter-article
-           gnus-newsgroup-name article
-           (gnus-summary-article-header article)
-           (= mark gnus-ticked-mark)
-           (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
-
-    ;; Fix the mark.
-    (gnus-summary-update-mark mark 'unread)
+    (if (< article 0)
+       (gnus-error 1 "Unmarkable article")
+      (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+      (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
+      (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
+      (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
+      (cond ((= mark gnus-ticked-mark)
+            (push article gnus-newsgroup-marked))
+           ((= mark gnus-dormant-mark)
+            (push article gnus-newsgroup-dormant))
+           (t
+            (push article gnus-newsgroup-unreads)))
+      (setq gnus-newsgroup-reads
+           (delq (assq article gnus-newsgroup-reads)
+                 gnus-newsgroup-reads))
+
+      ;; See whether the article is to be put in the cache.
+      (and gnus-use-cache
+          (vectorp (gnus-summary-article-header article))
+          (save-excursion
+            (gnus-cache-possibly-enter-article
+             gnus-newsgroup-name article
+             (gnus-summary-article-header article)
+             (= mark gnus-ticked-mark)
+             (= mark gnus-dormant-mark) (= mark gnus-unread-mark))))
+
+      ;; Fix the mark.
+      (gnus-summary-update-mark mark 'unread))
     t))
 
 (defun gnus-summary-mark-article (&optional article mark no-expire)
@@ -11643,9 +12257,10 @@ marked."
   (beginning-of-line)
   (let ((forward (cdr (assq type gnus-summary-mark-positions)))
        (buffer-read-only nil))
-    (when forward
+    (when (and forward
+              (<= (+ forward (point)) (point-max)))
       ;; Go to the right position on the line.
-      (forward-char forward)
+      (goto-char (+ forward (point)))
       ;; Replace the old mark with the new mark.
       (subst-char-in-region (point) (1+ (point)) (following-char) mark)
       ;; Optionally update the marks by some user rule.
@@ -11714,6 +12329,7 @@ The difference between N and the number of articles ticked is returned."
   "Mark current article as unread.
 Optional 1st argument ARTICLE specifies article number to be marked as unread.
 Optional 2nd argument CLEAR-MARK remove any kinds of mark."
+  (interactive)
   (gnus-summary-mark-article article (if clear-mark gnus-unread-mark
                                       gnus-ticked-mark)))
 
@@ -11756,6 +12372,13 @@ The difference between N and the number of marks cleared is returned."
   (when (memq gnus-current-article gnus-newsgroup-unreads)
     (gnus-summary-mark-article gnus-current-article gnus-read-mark)))
 
+(defun gnus-summary-mark-read-and-unread-as-read ()
+  "Intended to be used by `gnus-summary-mark-article-hook'."
+  (let ((mark (gnus-summary-article-mark)))
+    (when (or (gnus-unread-mark-p mark)
+             (gnus-read-mark-p mark))
+      (gnus-summary-mark-article gnus-current-article gnus-read-mark))))
+
 (defun gnus-summary-mark-region-as-read (point mark all)
   "Mark all unread articles between point and mark as read.
 If given a prefix, mark all articles between point and mark as read,
@@ -11835,9 +12458,9 @@ even ticked and dormant ones."
     (let ((scored gnus-newsgroup-scored)
          headers h)
       (while scored
-       (or (gnus-summary-goto-subject (car (car scored)))
-           (and (setq h (gnus-summary-article-header (car (car scored))))
-                (< (cdr (car scored)) gnus-summary-expunge-below)
+       (or (gnus-summary-goto-subject (caar scored))
+           (and (setq h (gnus-summary-article-header (caar scored)))
+                (< (cdar scored) gnus-summary-expunge-below)
                 (setq headers (cons h headers))))
        (setq scored (cdr scored)))
       (or headers (error "No expunged articles hidden."))
@@ -11894,10 +12517,11 @@ If ALL is non-nil, also mark ticked and dormant articles as read."
   (interactive "P")
   (gnus-set-global-variables)
   (save-excursion
-    (let ((beg (point)))
-      ;; We check that there are unread articles.
-      (when (or all (gnus-summary-find-prev))
-       (gnus-summary-catchup all t beg))))
+    (gnus-save-hidden-threads
+      (let ((beg (point)))
+       ;; We check that there are unread articles.
+       (when (or all (gnus-summary-find-prev))
+         (gnus-summary-catchup all t beg)))))
   (gnus-summary-position-point))
 
 (defun gnus-summary-catchup-all (&optional quietly)
@@ -11932,7 +12556,7 @@ read."
   (gnus-set-global-variables)
   (save-excursion
     (gnus-summary-catchup all))
-  (gnus-summary-next-article t))
+  (gnus-summary-next-article t nil nil t))
 
 ;; Thread-based commands.
 
@@ -11951,26 +12575,27 @@ with that article."
                 (gnus-simplify-subject-fuzzy
                  (mail-header-subject (gnus-data-header (car data)))))
                (t nil)))
+        (end-point (save-excursion
+                     (if (gnus-summary-go-to-next-thread) 
+                         (point) (point-max))))
         articles)
-    (if (not data)
-       ()                              ; This article doesn't exist.
-      (while data
-       (and (or (not top-subject)
-                (string= top-subject
-                         (if (eq gnus-thread-operation-ignore-subject 'fuzzy)
-                             (gnus-simplify-subject-fuzzy
-                              (mail-header-subject
-                               (gnus-data-header (car data))))
-                           (gnus-simplify-subject-re
-                            (mail-header-subject
-                             (gnus-data-header (car data)))))))
-            (setq articles (cons (gnus-data-number (car data)) articles)))
-       (if (and (setq data (cdr data))
-                (> (gnus-data-level (car data)) top-level))
-           ()
-         (setq data nil)))
-      ;; Return the list of articles.
-      (nreverse articles))))
+    (while (and data
+               (< (gnus-data-pos (car data)) end-point))
+      (when (or (not top-subject)
+               (string= top-subject
+                        (if (eq gnus-thread-operation-ignore-subject 'fuzzy)
+                            (gnus-simplify-subject-fuzzy
+                             (mail-header-subject
+                              (gnus-data-header (car data))))
+                          (gnus-simplify-subject-re
+                           (mail-header-subject
+                            (gnus-data-header (car data)))))))
+       (push (gnus-data-number (car data)) articles))
+      (unless (and (setq data (cdr data))
+                  (> (gnus-data-level (car data)) top-level))
+       (setq data nil)))
+    ;; Return the list of articles.
+    (nreverse articles)))
 
 (defun gnus-summary-rethread-current ()
   "Rethread the thread the current article is part of."
@@ -12014,7 +12639,7 @@ is non-nil or the Subject: of both articles are the same."
        (gnus-summary-select-article t t nil current-article)
        (set-buffer gnus-article-buffer)
        (setq buffer-read-only nil)
-       (let ((buf (buffer-substring-no-properties (point-min) (point-max))))
+       (let ((buf (format "%s" (buffer-string))))
          (erase-buffer)
          (insert buf))
        (goto-char (point-min))
@@ -12028,8 +12653,8 @@ is non-nil or the Subject: of both articles are the same."
        (set-buffer gnus-summary-buffer)
        (gnus-summary-unmark-all-processable)
        (gnus-summary-rethread-current)
-       (message "Article %d is now the child of article %d."
-                current-article parent-article)))))
+       (gnus-message 3 "Article %d is now the child of article %d."
+                     current-article parent-article)))))
 
 (defun gnus-summary-toggle-threads (&optional arg)
   "Toggle showing conversation threads.
@@ -12088,14 +12713,13 @@ Returns nil if no threads were there to be hidden."
   (gnus-set-global-variables)
   (let ((buffer-read-only nil)
        (start (point))
-       (article (gnus-summary-article-number))
-       end)
+       (article (gnus-summary-article-number)))
+    (goto-char start)
     ;; Go forward until either the buffer ends or the subthread
     ;; ends.
     (when (and (not (eobp))
               (or (zerop (gnus-summary-next-thread 1 t))
-                  (goto-char (gnus-data-pos (car (gnus-data-list 'rev))))))
-      (setq end (point))
+                  (goto-char (point-max))))
       (prog1
          (if (and (> (point) start)
                   (search-backward "\n" start t))
@@ -12104,23 +12728,56 @@ Returns nil if no threads were there to be hidden."
                (gnus-summary-goto-subject article))
            (goto-char start)
            nil)
-       (gnus-summary-position-point)))))
+       ;;(gnus-summary-position-point)
+       ))))
 
 (defun gnus-summary-go-to-next-thread (&optional previous)
   "Go to the same level (or less) next thread.
 If PREVIOUS is non-nil, go to previous thread instead.
 Return the article number moved to, or nil if moving was impossible."
-  (let* ((level (gnus-summary-thread-level))
-        (article (gnus-summary-article-number))
-        (data (cdr (gnus-data-find-list article (gnus-data-list previous))))
-        oart)
-    (while data
-      (if (<= (gnus-data-level (car data)) level)
-         (setq oart (gnus-data-number (car data))
-               data nil)
-       (setq data (cdr data))))
-    (and oart
-        (gnus-summary-goto-subject oart))))
+  (let ((level (gnus-summary-thread-level))
+       (way (if previous -1 1))
+       (beg (point)))
+    (forward-line way)
+    (while (and (not (eobp))
+               (< level (gnus-summary-thread-level)))
+      (forward-line way))
+    (if (eobp)
+       (progn
+         (goto-char beg)
+         nil)
+      (setq beg (point))
+      (prog1
+         (gnus-summary-article-number)
+       (goto-char beg)))))
+
+(defun gnus-summary-go-to-next-thread-old (&optional previous)
+  "Go to the same level (or less) next thread.
+If PREVIOUS is non-nil, go to previous thread instead.
+Return the article number moved to, or nil if moving was impossible."
+  (if (and (eq gnus-summary-make-false-root 'dummy)
+          (gnus-summary-article-intangible-p))
+      (let ((beg (point)))
+       (while (and (zerop (forward-line 1))
+                   (not (gnus-summary-article-intangible-p))
+                   (not (zerop (save-excursion 
+                                 (gnus-summary-thread-level))))))
+       (if (eobp)
+           (progn
+             (goto-char beg)
+             nil)
+         (point)))
+    (let* ((level (gnus-summary-thread-level))
+          (article (gnus-summary-article-number))
+          (data (cdr (gnus-data-find-list article (gnus-data-list previous))))
+          oart)
+      (while data
+       (if (<= (gnus-data-level (car data)) level)
+           (setq oart (gnus-data-number (car data))
+                 data nil)
+         (setq data (cdr data))))
+      (and oart
+          (gnus-summary-goto-subject oart)))))
 
 (defun gnus-summary-next-thread (n &optional silent)
   "Go to the same level next N'th thread.
@@ -12133,16 +12790,12 @@ If SILENT, don't output messages."
   (gnus-set-global-variables)
   (let ((backward (< n 0))
        (n (abs n))
-       old dum)
+       old dum int)
     (while (and (> n 0)
-               (setq old (save-excursion (forward-line 1) (point)))
                (gnus-summary-go-to-next-thread backward))
-      (when (and (eq gnus-summary-make-false-root 'dummy)
-                (setq dum (text-property-not-all
-                           old (point) 'gnus-intangible nil)))
-       (goto-char dum))
       (decf n))
-    (gnus-summary-position-point)
+    (unless silent 
+      (gnus-summary-position-point))
     (when (and (not silent) (/= 0 n))
       (gnus-message 7 "No more threads"))
     n))
@@ -12206,8 +12859,8 @@ If the prefix argument is positive, remove any kinds of marks.
 If the prefix argument is negative, tick articles instead."
   (interactive "P")
   (gnus-set-global-variables)
-  (if unmark
-      (setq unmark (prefix-numeric-value unmark)))
+  (when unmark
+    (setq unmark (prefix-numeric-value unmark)))
   (let ((articles (gnus-summary-articles-in-thread)))
     (save-excursion
       ;; Expand the thread.
@@ -12298,16 +12951,19 @@ Argument REVERSE means reverse order."
 (defun gnus-sortable-date (date)
   "Make sortable string by string-lessp from DATE.
 Timezone package is used."
-  (let* ((date (timezone-fix-time date nil nil)) ;[Y M D H M S]
-        (year (aref date 0))
-        (month (aref date 1))
-        (day (aref date 2)))
-    (timezone-make-sortable-date
-     year month day
-     (timezone-make-time-string
-      (aref date 3) (aref date 4) (aref date 5)))))
-
-
+  (condition-case ()
+      (progn
+       (setq date (inline (timezone-fix-time 
+                           date nil 
+                           (aref (inline (timezone-parse-date date)) 4))))
+       (inline
+         (timezone-make-sortable-date
+          (aref date 0) (aref date 1) (aref date 2)
+          (inline
+            (timezone-make-time-string
+             (aref date 3) (aref date 4) (aref date 5))))))
+    (error "")))
+  
 ;; Summary saving commands.
 
 (defun gnus-summary-save-article (&optional n not-saved)
@@ -12320,6 +12976,8 @@ The variable `gnus-default-article-saver' specifies the saver function."
   (interactive "P")
   (gnus-set-global-variables)
   (let ((articles (gnus-summary-work-articles n))
+       (save-buffer (save-excursion 
+                      (nnheader-set-temp-buffer " *Gnus Save*")))
        file header article)
     (while articles
       (setq header (gnus-summary-article-header
@@ -12332,33 +12990,37 @@ The variable `gnus-default-article-saver' specifies the saver function."
        ;; This is a real article.
        (save-window-excursion
          (gnus-summary-select-article t nil nil article))
+       (save-excursion
+         (set-buffer save-buffer)
+         (erase-buffer)
+         (insert-buffer-substring gnus-original-article-buffer))
        (unless gnus-save-all-headers
          ;; Remove headers accoring to `gnus-saved-headers'.
          (let ((gnus-visible-headers
-                (or gnus-saved-headers gnus-visible-headers)))
-           (gnus-article-hide-headers nil t)))
-       ;; Remove any X-Gnus lines.
-       (save-excursion
-         (set-buffer gnus-article-buffer)
-         (save-restriction
-           (let ((buffer-read-only nil))
-             (nnheader-narrow-to-headers)
-             (while (re-search-forward "^X-Gnus" nil t)
-               (gnus-delete-line)))))
+                (or gnus-saved-headers gnus-visible-headers))
+               (gnus-article-buffer save-buffer))
+           (gnus-article-hide-headers 1 t)))
        (save-window-excursion
          (if (not gnus-default-article-saver)
              (error "No default saver is defined.")
-           (setq file (funcall
-                       gnus-default-article-saver
-                       (cond
-                        ((not gnus-prompt-before-saving)
-                         'default)
-                        ((eq gnus-prompt-before-saving 'always)
-                         nil)
-                        (t file))))))
+           ;; !!! Magic!  The saving functions all save
+           ;; `gnus-original-article-buffer' (or so they think),
+           ;; but we bind that variable to our save-buffer.
+           (set-buffer gnus-article-buffer)
+           (let ((gnus-original-article-buffer save-buffer))
+             (set-buffer gnus-summary-buffer)
+             (setq file (funcall
+                         gnus-default-article-saver
+                         (cond
+                          ((not gnus-prompt-before-saving)
+                           'default)
+                          ((eq gnus-prompt-before-saving 'always)
+                           nil)
+                          (t file)))))))
        (gnus-summary-remove-process-mark article)
        (unless not-saved
          (gnus-summary-set-saved-mark article))))
+    (gnus-kill-buffer save-buffer)
     (gnus-summary-position-point)
     n))
 
@@ -12429,7 +13091,7 @@ save those articles instead."
          (while methods
            (goto-char (point-min))
            (setq method (pop methods))
-           (setq match (pop method))
+           (setq match (car method))
            (when (cond
                   ((stringp match)
                    ;; Regular expression.
@@ -12446,7 +13108,7 @@ save those articles instead."
                    (save-restriction
                      (widen)
                      (setq result (eval match)))))
-             (setq split-name (append (cdr methods) split-name))
+             (setq split-name (append (cdr method) split-name))
              (cond ((stringp result)
                     (push result split-name))
                    ((consp result)
@@ -12456,8 +13118,21 @@ save those articles instead."
 (defun gnus-read-move-group-name (prompt default articles prefix)
   "Read a group name."
   (let* ((split-name (gnus-get-split-value gnus-move-split-methods))
+        (minibuffer-confirm-incomplete nil) ; XEmacs
+        group-map
+        (dum (mapatoms
+              (lambda (g) 
+                (and (boundp g)
+                     (symbol-name g)
+                     (memq 'respool
+                           (assoc (symbol-name
+                                   (car (gnus-find-method-for-group
+                                         (symbol-name g))))
+                                  gnus-valid-select-methods))
+                     (push (list (symbol-name g)) group-map)))
+              gnus-active-hashtb))
         (prom
-         (format "Where do you want to %s %s? "
+         (format "%s %s to:"
                  prompt
                  (if (> (length articles) 1)
                      (format "these %d articles" (length articles))
@@ -12465,25 +13140,33 @@ save those articles instead."
         (to-newsgroup
          (cond
           ((null split-name)
-           (completing-read
-            (concat prom
-                    (if default
-                        (format "(default %s) " default)
-                      ""))
-            gnus-active-hashtb nil nil prefix))
+           (gnus-completing-read default prom
+                                 group-map nil nil prefix
+                                 'gnus-group-history))
           ((= 1 (length split-name))
-           (completing-read prom gnus-active-hashtb
-                            nil nil (cons (car split-name) 0)))
+           (gnus-completing-read (car split-name) prom group-map
+                                 nil nil nil
+                                 'gnus-group-history))
           (t
-           (completing-read
-            prom (mapcar (lambda (el) (list el)) (nreverse split-name)))))))
-
+           (gnus-completing-read nil prom 
+                                 (mapcar (lambda (el) (list el))
+                                         (nreverse split-name))
+                                 nil nil nil
+                                 'gnus-group-history)))))
     (when to-newsgroup
       (if (or (string= to-newsgroup "")
              (string= to-newsgroup prefix))
          (setq to-newsgroup (or default "")))
       (or (gnus-active to-newsgroup)
          (gnus-activate-group to-newsgroup)
+         (if (gnus-y-or-n-p (format "No such group: %s.  Create it? "
+                                    to-newsgroup))
+             (or (and (gnus-request-create-group 
+                       to-newsgroup (gnus-group-name-to-method to-newsgroup))
+                      (gnus-activate-group to-newsgroup nil nil
+                                           (gnus-group-name-to-method
+                                            to-newsgroup)))
+                 (error "Couldn't create group %s" to-newsgroup)))
          (error "No such group: %s" to-newsgroup)))
     to-newsgroup))
 
@@ -12501,20 +13184,25 @@ save those articles instead."
             default-name))
           ;; A single split name was found
           ((= 1 (length split-name))
-           (read-file-name
-            (concat prompt " (default " (car split-name) ") ")
-            gnus-article-save-directory
-            (concat gnus-article-save-directory (car split-name))))
+           (let* ((name (car split-name))
+                  (dir (cond ((file-directory-p name)
+                              (file-name-as-directory name))
+                             ((file-exists-p name) name)
+                             (t gnus-article-save-directory))))
+             (read-file-name
+              (concat prompt " (default " name ") ")
+              dir name)))
           ;; A list of splits was found.
           (t
-           (setq split-name (mapcar (lambda (el) (list el))
-                                    (nreverse split-name)))
-           (let ((result (completing-read
-                          (concat prompt " ") split-name nil nil)))
-             (concat gnus-article-save-directory
-                     (if (string= result "")
-                         (car (car split-name))
-                       result)))))))
+           (setq split-name (nreverse split-name))
+           (let (result)
+             (let ((file-name-history (nconc split-name file-name-history)))
+               (setq result
+                     (read-file-name
+                      (concat prompt " (`M-p' for defaults) ")
+                      gnus-article-save-directory
+                      (car split-name))))
+             (car (push result file-name-history)))))))
     ;; If we have read a directory, we append the default file name.
     (when (file-directory-p file)
       (setq file (concat (file-name-as-directory file)
@@ -12531,8 +13219,7 @@ save those articles instead."
 (defun gnus-summary-save-in-rmail (&optional filename)
   "Append this article to Rmail file.
 Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
+Directory to save to is default to `gnus-article-save-directory'."
   (interactive)
   (gnus-set-global-variables)
   (let ((default-name
@@ -12545,20 +13232,18 @@ is initialized from the SAVEDIR environment variable."
                (t (gnus-read-save-file-name
                    "Save in rmail file:" default-name))))
     (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window
-     gnus-original-article-buffer
-     (save-excursion
-       (save-restriction
-        (widen)
-        (gnus-output-to-rmail filename))))
+    (gnus-eval-in-buffer-window gnus-original-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (gnus-output-to-rmail filename))))
     ;; Remember the directory name to save articles
     (setq gnus-newsgroup-last-rmail filename)))
 
 (defun gnus-summary-save-in-mail (&optional filename)
   "Append this article to Unix mail file.
 Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
+Directory to save to is default to `gnus-article-save-directory'."
   (interactive)
   (gnus-set-global-variables)
   (let ((default-name
@@ -12575,23 +13260,21 @@ is initialized from the SAVEDIR environment variable."
                            (and default-name
                                 (file-name-directory default-name))))
     (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window
-     gnus-original-article-buffer
-     (save-excursion
-       (save-restriction
-        (widen)
-        (if (and (file-readable-p filename) (mail-file-babyl-p filename))
-            (gnus-output-to-rmail filename)
-          (let ((mail-use-rfc822 t))
-            (rmail-output filename 1 t t))))))
+    (gnus-eval-in-buffer-window gnus-original-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (if (and (file-readable-p filename) (mail-file-babyl-p filename))
+             (gnus-output-to-rmail filename)
+           (let ((mail-use-rfc822 t))
+             (rmail-output filename 1 t t))))))
     ;; Remember the directory name to save articles.
     (setq gnus-newsgroup-last-mail filename)))
 
 (defun gnus-summary-save-in-file (&optional filename)
   "Append this article to file.
 Optional argument FILENAME specifies file name.
-Directory to save to is default to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
+Directory to save to is default to `gnus-article-save-directory'."
   (interactive)
   (gnus-set-global-variables)
   (let ((default-name
@@ -12604,20 +13287,18 @@ is initialized from the SAVEDIR environment variable."
                (t (gnus-read-save-file-name
                    "Save in file:" default-name))))
     (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (save-excursion
-       (save-restriction
-        (widen)
-        (gnus-output-to-file filename))))
+    (gnus-eval-in-buffer-window gnus-original-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (gnus-output-to-file filename))))
     ;; Remember the directory name to save articles.
     (setq gnus-newsgroup-last-file filename)))
 
 (defun gnus-summary-save-body-in-file (&optional filename)
   "Append this article body to a file.
 Optional argument FILENAME specifies file name.
-The directory to save in defaults to `gnus-article-save-directory' which
-is initialized from the SAVEDIR environment variable."
+The directory to save in defaults to `gnus-article-save-directory'."
   (interactive)
   (gnus-set-global-variables)
   (let ((default-name
@@ -12630,16 +13311,15 @@ is initialized from the SAVEDIR environment variable."
                (t (gnus-read-save-file-name
                    "Save body in file:" default-name))))
     (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window
-     gnus-article-buffer
-     (save-excursion
-       (save-restriction
-        (widen)
-        (goto-char (point-min))
-        (and (search-forward "\n\n" nil t)
-             (narrow-to-region (point) (point-max)))
-        (gnus-output-to-file filename))))
-    ;; Remember the directory name to save articles.
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (goto-char (point-min))
+         (and (search-forward "\n\n" nil t)
+              (narrow-to-region (point) (point-max)))
+         (gnus-output-to-file filename))))
+    ;; Remember the directory name to save articles.
     (setq gnus-newsgroup-last-file filename)))
 
 (defun gnus-summary-save-in-pipe (&optional command)
@@ -12654,11 +13334,10 @@ is initialized from the SAVEDIR environment variable."
                              gnus-last-shell-command))))
   (if (string-equal command "")
       (setq command gnus-last-shell-command))
-  (gnus-eval-in-buffer-window
-   gnus-article-buffer
-   (save-restriction
-     (widen)
-     (shell-command-on-region (point-min) (point-max) command nil)))
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (save-restriction
+      (widen)
+      (shell-command-on-region (point-min) (point-max) command nil)))
   (setq gnus-last-shell-command command))
 
 ;; Summary extract commands
@@ -12681,9 +13360,9 @@ is initialized from the SAVEDIR environment variable."
          (setq files (list (cdr (assq 'name (car ps)))))
          (while (and ps (cdr ps)
                      (string= (or action "1")
-                              (or (cdr (assq 'action (car (cdr ps)))) "2")))
-           (setq files (cons (cdr (assq 'name (car (cdr ps)))) files))
-           (setcdr ps (cdr (cdr ps))))
+                              (or (cdr (assq 'action (cadr ps))) "2")))
+           (setq files (cons (cdr (assq 'name (cadr ps))) files))
+           (setcdr ps (cddr ps)))
          (if (not files)
              ()
            (if (not (string-match "%s" action))
@@ -12709,14 +13388,14 @@ is initialized from the SAVEDIR environment variable."
          (gnus-summary-goto-subject after-article)
          (forward-line 1)
          (setq b (point))
-         (insert "          " (file-name-nondirectory
+         (insert "    " (file-name-nondirectory
                                (cdr (assq 'name (car pslist))))
                  ": " (or (cdr (assq 'execute (car pslist))) "") "\n")
          (setq e (point))
          (forward-line -1)             ; back to `b'
-         (add-text-properties
-          b e (list 'gnus-number gnus-reffed-article-number
-                    gnus-mouse-face-prop gnus-mouse-face))
+         (gnus-add-text-properties
+          b (1- e) (list 'gnus-number gnus-reffed-article-number
+                         gnus-mouse-face-prop gnus-mouse-face))
          (gnus-data-enter
           after-article gnus-reffed-article-number
           gnus-unread-mark b (car pslist) 0 (- e b))
@@ -12739,13 +13418,20 @@ is initialized from the SAVEDIR environment variable."
   (save-excursion
     (gnus-article-setup-buffer)
     (set-buffer gnus-article-buffer)
+    (setq buffer-read-only nil)
     (let ((command (if automatic command (read-string "Command: " command)))
-         (buffer-read-only nil))
+         ;; Just binding this here doesn't help, because there might
+         ;; be output from the process after exiting the scope of 
+         ;; this `let'.
+         ;; (buffer-read-only nil)
+         )
       (erase-buffer)
       (insert "$ " command "\n\n")
       (if gnus-view-pseudo-asynchronously
-         (start-process "gnus-execute" nil "sh" "-c" command)
-       (call-process "sh" nil t nil "-c" command)))))
+         (start-process "gnus-execute" nil shell-file-name
+                        shell-command-switch command)
+       (call-process shell-file-name nil t nil
+                     shell-command-switch command)))))
 
 (defun gnus-copy-file (file &optional to)
   "Copy FILE to TO."
@@ -12788,25 +13474,26 @@ is initialized from the SAVEDIR environment variable."
   (setq gnus-article-mode-map (make-keymap))
   (suppress-keymap gnus-article-mode-map)
 
-  (gnus-define-keys
-   gnus-article-mode-map
-   " " gnus-article-goto-next-page
-   "\177" gnus-article-goto-prev-page
-   "\C-c^" gnus-article-refer-article
-   "h" gnus-article-show-summary
-   "s" gnus-article-show-summary
-   "\C-c\C-m" gnus-article-mail
-   "?" gnus-article-describe-briefly
-   gnus-mouse-2 gnus-article-push-button
-   "\r" gnus-article-press-button
-   "\t" gnus-article-next-button
-   "\M-\t" gnus-article-prev-button
-   "\C-c\C-b" gnus-bug)
+  (gnus-define-keys gnus-article-mode-map
+    " " gnus-article-goto-next-page
+    "\177" gnus-article-goto-prev-page
+    [delete] gnus-article-goto-prev-page
+    "\C-c^" gnus-article-refer-article
+    "h" gnus-article-show-summary
+    "s" gnus-article-show-summary
+    "\C-c\C-m" gnus-article-mail
+    "?" gnus-article-describe-briefly
+    gnus-mouse-2 gnus-article-push-button
+    "\r" gnus-article-press-button
+    "\t" gnus-article-next-button
+    "\M-\t" gnus-article-prev-button
+    "<" beginning-of-buffer
+    ">" end-of-buffer
+    "\C-c\C-b" gnus-bug)
 
   (substitute-key-definition
    'undefined 'gnus-article-read-summary-keys gnus-article-mode-map))
 
-
 (defun gnus-article-mode ()
   "Major mode for displaying an article.
 
@@ -12856,8 +13543,15 @@ The following commands are available:
       (save-excursion
        (set-buffer gnus-summary-buffer)
        (setq gnus-article-buffer name)
-       (setq gnus-original-article-buffer original))
+       (setq gnus-original-article-buffer original)
+       (gnus-set-global-variables))
       (make-local-variable 'gnus-summary-buffer))
+    ;; Init original article buffer.
+    (save-excursion
+      (set-buffer (get-buffer-create gnus-original-article-buffer))
+      (buffer-disable-undo (current-buffer))
+      (setq major-mode 'gnus-original-article-mode)
+      (make-local-variable 'gnus-original-article))
     (if (get-buffer name)
        (save-excursion
          (set-buffer name)
@@ -12877,7 +13571,7 @@ The following commands are available:
 ;; from the head of the article.
 (defun gnus-article-set-window-start (&optional line)
   (set-window-start
-   (get-buffer-window gnus-article-buffer)
+   (get-buffer-window gnus-article-buffer t)
    (save-excursion
      (set-buffer gnus-article-buffer)
      (goto-char (point-min))
@@ -12899,160 +13593,207 @@ The following commands are available:
 
 (defun gnus-request-article-this-buffer (article group)
   "Get an article and insert it into this buffer."
-  (prog1
-      (save-excursion
-       (if (get-buffer gnus-original-article-buffer)
-           (set-buffer (get-buffer gnus-original-article-buffer))
-         (set-buffer (get-buffer-create gnus-original-article-buffer))
-         (buffer-disable-undo (current-buffer))
-         (setq major-mode 'gnus-original-article-mode)
-         (setq buffer-read-only t)
-         (gnus-add-current-to-buffer-list))
-
-       (setq group (or group gnus-newsgroup-name))
-
-       ;; Open server if it has closed.
-       (gnus-check-server (gnus-find-method-for-group group))
-
-       ;; Using `gnus-request-article' directly will insert the article into
-       ;; `nntp-server-buffer' - so we'll save some time by not having to
-       ;; copy it from the server buffer into the article buffer.
-
-       ;; We only request an article by message-id when we do not have the
-       ;; headers for it, so we'll have to get those.
-       (when (stringp article)
-         (let ((gnus-override-method gnus-refer-article-method))
-           (gnus-read-header article)))
-
-       ;; If the article number is negative, that means that this article
-       ;; doesn't belong in this newsgroup (possibly), so we find its
-       ;; message-id and request it by id instead of number.
-       (when (numberp article)
-         (save-excursion
-           (set-buffer gnus-summary-buffer)
-           (let ((header (gnus-summary-article-header article)))
-             (if (< article 0)
-                 (cond 
-                  ((memq article gnus-newsgroup-sparse)
-                   ;; This is a sparse gap article.
-                   (setq article (mail-header-id header)))
-                  ((vectorp header)
-                   ;; It's a real article.
-                   (setq article (mail-header-id header)))
-                  (t
-                   ;; It is an extracted pseudo-article.
-                   (setq article 'pseudo)
-                   (gnus-request-pseudo-article header))))
+  (let (do-update-line)
+    (prog1
+       (save-excursion
+         (erase-buffer)
+         (gnus-kill-all-overlays)
+         (setq group (or group gnus-newsgroup-name))
+
+         ;; Open server if it has closed.
+         (gnus-check-server (gnus-find-method-for-group group))
+
+         ;; Using `gnus-request-article' directly will insert the article into
+         ;; `nntp-server-buffer' - so we'll save some time by not having to
+         ;; copy it from the server buffer into the article buffer.
+
+         ;; We only request an article by message-id when we do not have the
+         ;; headers for it, so we'll have to get those.
+         (when (stringp article)
+           (let ((gnus-override-method gnus-refer-article-method))
+             (gnus-read-header article)))
+
+         ;; If the article number is negative, that means that this article
+         ;; doesn't belong in this newsgroup (possibly), so we find its
+         ;; message-id and request it by id instead of number.
+         (when (and (numberp article)
+                    gnus-summary-buffer
+                    (get-buffer gnus-summary-buffer)
+                    (buffer-name (get-buffer gnus-summary-buffer)))
+           (save-excursion
+             (set-buffer gnus-summary-buffer)
+             (let ((header (gnus-summary-article-header article)))
+               (if (< article 0)
+                   (cond 
+                    ((memq article gnus-newsgroup-sparse)
+                     ;; This is a sparse gap article.
+                     (setq do-update-line article)
+                     (setq article (mail-header-id header))
+                     (let ((gnus-override-method gnus-refer-article-method))
+                       (gnus-read-header article))
+                     (setq gnus-newsgroup-sparse
+                           (delq article gnus-newsgroup-sparse)))
+                    ((vectorp header)
+                     ;; It's a real article.
+                     (setq article (mail-header-id header)))
+                    (t
+                     ;; It is an extracted pseudo-article.
+                     (setq article 'pseudo)
+                     (gnus-request-pseudo-article header))))
                
-             (let ((method (gnus-find-method-for-group 
-                            gnus-newsgroup-name)))
-               (if (not (eq (car method) 'nneething))
-                   ()
-                 (let ((dir (concat (file-name-as-directory (nth 1 method))
-                                    (mail-header-subject header))))
-                   (if (file-directory-p dir)
-                       (progn
-                         (setq article 'nneething)
-                         (gnus-group-enter-directory dir)))))))))
-
-       (cond
-        ;; We first check `gnus-original-article-buffer'.
-        ((and (equal (car gnus-original-article) group)
-              (eq (cdr gnus-original-article) article))
-         ;; We don't have to do anything, since it's already where we
-         ;; want it.
-         'article)
-        ;; Check the backlog.
-        ((and gnus-keep-backlog
-              (gnus-backlog-request-article group article (current-buffer)))
-         'article)
-        ;; Check the cache.
-        ((and gnus-use-cache
-              (numberp article)
-              (gnus-cache-request-article article group))
-         'article)
-        ;; Get the article and put into the article buffer.
-        ((or (stringp article) (numberp article))
-         (let ((gnus-override-method
-                (and (stringp article) gnus-refer-article-method))
-               (buffer-read-only nil))
+               (let ((method (gnus-find-method-for-group 
+                              gnus-newsgroup-name)))
+                 (if (not (eq (car method) 'nneething))
+                     ()
+                   (let ((dir (concat (file-name-as-directory (nth 1 method))
+                                      (mail-header-subject header))))
+                     (if (file-directory-p dir)
+                         (progn
+                           (setq article 'nneething)
+                           (gnus-group-enter-directory dir)))))))))
+
+         (cond
+          ;; Refuse to select canceled articles.
+          ((and (numberp article)
+                gnus-summary-buffer
+                (get-buffer gnus-summary-buffer)
+                (buffer-name (get-buffer gnus-summary-buffer))
+                (eq (cdr (save-excursion
+                           (set-buffer gnus-summary-buffer)
+                           (assq article gnus-newsgroup-reads)))
+                    gnus-canceled-mark))
+           nil)
+          ;; We first check `gnus-original-article-buffer'.
+          ((and (get-buffer gnus-original-article-buffer)
+                (numberp article)
+                (save-excursion
+                  (set-buffer gnus-original-article-buffer)
+                  (and (equal (car gnus-original-article) group)
+                       (eq (cdr gnus-original-article) article))))
+           (insert-buffer-substring gnus-original-article-buffer)
+           'article)
+          ;; Check the backlog.
+          ((and gnus-keep-backlog
+                (gnus-backlog-request-article group article (current-buffer)))
+           'article)
+          ;; Check the cache.
+          ((and gnus-use-cache
+                (numberp article)
+                (gnus-cache-request-article article group))
+           'article)
+          ;; Get the article and put into the article buffer.
+          ((or (stringp article) (numberp article))
+           (let ((gnus-override-method
+                  (and (stringp article) gnus-refer-article-method))
+                 (buffer-read-only nil))
+             (erase-buffer)
+             (gnus-kill-all-overlays)
+             (if (gnus-request-article article group (current-buffer))
+                 (progn
+                   (and gnus-keep-backlog
+                        (numberp article)
+                        (gnus-backlog-enter-article
+                         group article (current-buffer)))
+                   'article))))
+          ;; It was a pseudo.
+          (t article)))
+
+      ;; Take the article from the original article buffer
+      ;; and place it in the buffer it's supposed to be in.
+      (when (and (get-buffer gnus-article-buffer)
+                ;;(numberp article)
+                (equal (buffer-name (current-buffer))
+                       (buffer-name (get-buffer gnus-article-buffer))))
+       (save-excursion
+         (if (get-buffer gnus-original-article-buffer)
+             (set-buffer (get-buffer gnus-original-article-buffer))
+           (set-buffer (get-buffer-create gnus-original-article-buffer))
+           (buffer-disable-undo (current-buffer))
+           (setq major-mode 'gnus-original-article-mode)
+           (setq buffer-read-only t)
+           (gnus-add-current-to-buffer-list))
+         (let (buffer-read-only)
            (erase-buffer)
-           (gnus-kill-all-overlays)
-           (if (gnus-request-article article group (current-buffer))
-               (progn
-                 (and gnus-keep-backlog
-                      (gnus-backlog-enter-article
-                       group article (current-buffer)))
-                 'article))))
-        ;; It was a pseudo.
-        (t article)))
-
-    ;; Take the article from the original article buffer
-    ;; and place it in the buffer it's supposed to be in.
-    (setq gnus-original-article (cons group article))
-    (unless (equal (buffer-name (current-buffer))
-                  (buffer-name (get-buffer gnus-original-article-buffer)))
-      (let (buffer-read-only)
-       (erase-buffer)
-       (gnus-kill-all-overlays)
-       (insert-buffer-substring gnus-original-article-buffer)))
+           (insert-buffer-substring gnus-article-buffer))
+         (setq gnus-original-article (cons group article))))
     
-    ;; Update sparse articles.
-    (when (memq article gnus-newsgroup-sparse)
-      (gnus-summary-update-article article))))
+      ;; Update sparse articles.
+      (when (and do-update-line
+                (or (numberp article)
+                    (stringp article)))
+       (let ((buf (current-buffer)))
+         (set-buffer gnus-summary-buffer)
+         (gnus-summary-update-article do-update-line)
+         (gnus-summary-goto-subject do-update-line nil t)
+         (set-window-point (get-buffer-window (current-buffer) t)
+                           (point))
+         (set-buffer buf))))))
 
-(defun gnus-read-header (id)
+(defun gnus-read-header (id &optional header)
   "Read the headers of article ID and enter them into the Gnus system."
   (let ((group gnus-newsgroup-name)
-       (headers gnus-newsgroup-headers)
-       header where)
+       (gnus-override-method 
+        (and (gnus-news-group-p gnus-newsgroup-name)
+             gnus-refer-article-method))       
+       where)
     ;; First we check to see whether the header in question is already
     ;; fetched.
     (if (stringp id)
        ;; This is a Message-ID.
-       (setq header (gnus-id-to-header id))
+       (setq header (or header (gnus-id-to-header id)))
       ;; This is an article number.
-      (setq header (gnus-summary-article-header id)))
-    (if header
+      (setq header (or header (gnus-summary-article-header id))))
+    (if (and header
+            (not (memq (mail-header-number header) gnus-newsgroup-sparse)))
        ;; We have found the header.
        header
       ;; We have to really fetch the header to this article.
-      (when (setq where
-                 (if (gnus-check-backend-function 'request-head group)
-                     (gnus-request-head id group)
-                   (gnus-request-article id group)))
+      (when (setq where (gnus-request-head id group))
        (save-excursion
          (set-buffer nntp-server-buffer)
-         (and (search-forward "\n\n" nil t)
-              (delete-region (1- (point)) (point-max)))
          (goto-char (point-max))
          (insert ".\n")
          (goto-char (point-min))
-         (insert "211 "
-                 (int-to-string
-                  (cond
-                   ((numberp id)
-                    id)
-                   ((cdr where)
-                    (cdr where))
-                   (t
-                    gnus-reffed-article-number)))
-                 " Article retrieved.\n"))
+         (insert "211 ")
+         (princ (cond
+                 ((numberp id) id)
+                 ((cdr where) (cdr where))
+                 (header (mail-header-number header))
+                 (t gnus-reffed-article-number))
+                (current-buffer))
+         (insert " Article retrieved.\n"))
+       ;(when (and header
+       ;          (memq (mail-header-number header) gnus-newsgroup-sparse))
+       ;  (setcar (gnus-id-to-thread id) nil))
        (if (not (setq header (car (gnus-get-newsgroup-headers))))
-           () ; Malformed head.
-         (if (and (stringp id)
-                  (not (string= (gnus-group-real-name group)
-                                (car where))))
-             ;; If we fetched by Message-ID and the article came
-             ;; from a different group, we fudge some bogus article
-             ;; numbers for this article.
-             (mail-header-set-number header gnus-reffed-article-number))
-         (decf gnus-reffed-article-number)
-         (push header gnus-newsgroup-headers)
-         (setq gnus-current-headers header)
-         (push (mail-header-number header) gnus-newsgroup-limit)
+           ()                          ; Malformed head.
+         (unless (memq (mail-header-number header) gnus-newsgroup-sparse)
+           (if (and (stringp id)
+                    (not (string= (gnus-group-real-name group)
+                                  (car where))))
+               ;; If we fetched by Message-ID and the article came
+               ;; from a different group, we fudge some bogus article
+               ;; numbers for this article.
+               (mail-header-set-number header gnus-reffed-article-number))
+           (decf gnus-reffed-article-number)
+           (gnus-remove-header (mail-header-number header))
+           (push header gnus-newsgroup-headers)
+           (setq gnus-current-headers header)
+           (push (mail-header-number header) gnus-newsgroup-limit))
          header)))))
 
+(defun gnus-remove-header (number)
+  "Remove header NUMBER from `gnus-newsgroup-headers'."
+  (if (and gnus-newsgroup-headers
+          (= number (mail-header-number (car gnus-newsgroup-headers))))
+      (pop gnus-newsgroup-headers)
+    (let ((headers gnus-newsgroup-headers))
+      (while (and (cdr headers)
+                 (not (= number (mail-header-number (cadr headers)))))
+       (pop headers))
+      (when (cdr headers)
+       (setcdr headers (cddr headers))))))
+
 (defun gnus-article-prepare (article &optional all-headers header)
   "Prepare ARTICLE in article mode buffer.
 ARTICLE should either be an article number or a Message-ID.
@@ -13093,10 +13834,8 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                (setq gnus-current-article article)
                (gnus-summary-mark-article article gnus-canceled-mark))
              (unless (memq article gnus-newsgroup-sparse)
-               (gnus-message
-                1 "No such article (may have expired or been canceled)")
-               (ding)
-               nil))
+               (gnus-error
+                1 "No such article (may have expired or been canceled)")))
          (if (or (eq result 'pseudo) (eq result 'nneething))
              (progn
                (save-excursion
@@ -13150,22 +13889,24 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                        (memq article gnus-newsgroup-marked)
                        (memq article gnus-newsgroup-dormant)
                        (memq article gnus-newsgroup-unreads)))))
-           ;; Hooks for getting information from the article.
-           ;; This hook must be called before being narrowed.
-           (let (buffer-read-only)
-             (run-hooks 'internal-hook)
-             (run-hooks 'gnus-article-prepare-hook)
-             ;; Decode MIME message.
-             (if gnus-show-mime
-                 (if (or (not gnus-strict-mime)
-                         (gnus-fetch-field "Mime-Version"))
-                     (funcall gnus-show-mime-method)
-                   (funcall gnus-decode-encoded-word-method)))
-             ;; Perform the article display hooks.
-             (run-hooks 'gnus-article-display-hook))
-           ;; Do page break.
-           (goto-char (point-min))
-           (and gnus-break-pages (gnus-narrow-to-page))
+           (when (or (numberp article)
+                     (stringp article))
+             ;; Hooks for getting information from the article.
+             ;; This hook must be called before being narrowed.
+             (let (buffer-read-only)
+               (run-hooks 'internal-hook)
+               (run-hooks 'gnus-article-prepare-hook)
+               ;; Decode MIME message.
+               (if gnus-show-mime
+                   (if (or (not gnus-strict-mime)
+                           (gnus-fetch-field "Mime-Version"))
+                       (funcall gnus-show-mime-method)
+                     (funcall gnus-decode-encoded-word-method)))
+               ;; Perform the article display hooks.
+               (run-hooks 'gnus-article-display-hook))
+             ;; Do page break.
+             (goto-char (point-min))
+             (and gnus-break-pages (gnus-narrow-to-page)))
            (gnus-set-mode-line 'article)
            (gnus-configure-windows 'article)
            (goto-char (point-min))
@@ -13177,8 +13918,7 @@ If ALL-HEADERS is non-nil, no headers are hidden."
     (gnus-article-setup-buffer)
     (set-buffer gnus-article-buffer)
     (let ((buffer-read-only nil))
-      (remove-text-properties (point-min) (point-max)
-                             gnus-hidden-properties))))
+      (gnus-unhide-text (point-min) (point-max)))))
 
 (defun gnus-article-hide-headers-if-wanted ()
   "Hide unwanted headers if `gnus-have-all-headers' is nil.
@@ -13187,18 +13927,34 @@ Provided for backwards compatibility."
       gnus-inhibit-hiding
       (gnus-article-hide-headers)))
 
+(defsubst gnus-article-header-rank ()
+  "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
+  (let ((list gnus-sorted-header-list)
+       (i 0))
+    (while list
+      (when (looking-at (car list))
+       (setq list nil))
+      (setq list (cdr list))
+      (incf i))
+    i))
+
 (defun gnus-article-hide-headers (&optional arg delete)
   "Toggle whether to hide unwanted headers and possibly sort them as well.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive "P")
-  (unless (gnus-article-check-hidden-text 'headers arg)
+  (interactive (gnus-hidden-arg))
+  (if (gnus-article-check-hidden-text 'headers arg)
+      ;; Show boring headers as well.
+      (gnus-article-show-hidden-text 'boring-headers)
     ;; This function might be inhibited.
     (unless gnus-inhibit-hiding
       (save-excursion
        (set-buffer gnus-article-buffer)
        (save-restriction
          (let ((buffer-read-only nil)
+               (props (nconc (list 'gnus-type 'headers)
+                             gnus-hidden-properties))
+               (max (1+ (length gnus-sorted-header-list)))
                (ignored (when (not (stringp gnus-visible-headers))
                           (cond ((stringp gnus-ignored-headers)
                                  gnus-ignored-headers)
@@ -13208,9 +13964,11 @@ always hide."
                (visible
                 (cond ((stringp gnus-visible-headers)
                        gnus-visible-headers)
-                      ((listp gnus-visible-headers)
+                      ((and gnus-visible-headers
+                            (listp gnus-visible-headers))
                        (mapconcat 'identity gnus-visible-headers "\\|"))))
-               want-list beg want-l)
+               (inhibit-point-motion-hooks t)
+               want-list beg)
            ;; First we narrow to just the headers.
            (widen)
            (goto-char (point-min))
@@ -13218,9 +13976,9 @@ always hide."
            (while (looking-at "From ")
              (forward-line 1))
            (unless (bobp)
-             (add-text-properties
-              (point-min) (point)
-              (nconc (list 'gnus-type 'headers) gnus-hidden-properties)))
+             (if delete
+                 (delete-region (point-min) (point))
+               (gnus-hide-text (point-min) (point) props)))
            ;; Then treat the rest of the header lines.
            (narrow-to-region
             (point)
@@ -13234,55 +13992,30 @@ always hide."
              (beginning-of-line)
              ;; We add the headers we want to keep to a list and delete
              ;; them from the buffer.
-             (if (or (and visible (looking-at visible))
-                     (and ignored (not (looking-at ignored))))
-                 (progn
-                   (push (buffer-substring
-                          (setq beg (point))
-                          (progn
-                            (forward-line 1)
-                            ;; Be sure to get multi-line headers...
-                            (re-search-forward "^[^ \t]*:" nil t)
-                            (beginning-of-line)
-                            (point)))
-                         want-list)
-                   (delete-region beg (point)))
-               (forward-line 1)))
-           ;; Sort the headers that we want to display.
-           (setq want-list (sort want-list 'gnus-article-header-less))
-           (goto-char (point-min))
-           (while want-list
-             (insert (pop want-list)))
-           ;; We make the unwanted headers invisible.
-           (if delete
-               (delete-region (point-min) (point-max))
-             ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
-             (add-text-properties
-              (point) (point-max)
-              (nconc (list 'gnus-type 'headers)
-                     gnus-hidden-properties)))))))))
-
-(defsubst gnus-article-header-rank (header)
-  "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
-  (let ((list gnus-sorted-header-list)
-       (i 0))
-    (while list
-      (when (string-match (car list) header)
-       (setq list nil))
-      (setq list (cdr list))
-      (incf i))
-    i))
-
-(defun gnus-article-header-less (h1 h2)
-  "Say whether string H1 is \"less\" than string H2."
-  (< (gnus-article-header-rank h1)
-     (gnus-article-header-rank h2)))
+             (gnus-put-text-property 
+              (point) (1+ (point)) 'message-rank
+              (if (or (and visible (looking-at visible))
+                      (and ignored
+                           (not (looking-at ignored))))
+                  (gnus-article-header-rank) 
+                (+ 2 max)))
+             (forward-line 1))
+           (message-sort-headers-1)
+           (when (setq beg (text-property-any 
+                            (point-min) (point-max) 'message-rank (+ 2 max)))
+             ;; We make the unwanted headers invisible.
+             (if delete
+                 (delete-region beg (point-max))
+               ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
+               (gnus-hide-text-type beg (point-max) 'headers))
+             ;; Work around XEmacs lossage.
+             (gnus-put-text-property (point-min) beg 'invisible nil))))))))
 
 (defun gnus-article-hide-boring-headers (&optional arg)
   "Toggle hiding of headers that aren't very interesting.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive "P")
+  (interactive (gnus-hidden-arg))
   (unless (gnus-article-check-hidden-text 'boring-headers arg)
     (save-excursion
       (set-buffer gnus-article-buffer)
@@ -13300,35 +14033,35 @@ always hide."
             ((eq elem 'empty)
              (while (re-search-forward "^[^:]+:[ \t]\n[^ \t]" nil t)
                (forward-line -1)
-               (add-text-properties
+               (gnus-hide-text-type
                 (progn (beginning-of-line) (point))
                 (progn 
                   (end-of-line)
                   (if (re-search-forward "^[^ \t]" nil t)
                       (match-beginning 0)
                     (point-max)))
-                (nconc (list 'gnus-type 'boring-headers)
-                       gnus-hidden-properties))))
+                'boring-headers)))
             ;; Hide boring Newsgroups header.
             ((eq elem 'newsgroups)
-             (when (equal (mail-fetch-field "newsgroups")
+             (when (equal (message-fetch-field "newsgroups")
                           (gnus-group-real-name gnus-newsgroup-name))
                (gnus-article-hide-header "newsgroups")))
             ((eq elem 'followup-to)
-             (when (equal (mail-fetch-field "followup-to")
-                          (mail-fetch-field "newsgroups"))
+             (when (equal (message-fetch-field "followup-to")
+                          (message-fetch-field "newsgroups"))
                (gnus-article-hide-header "followup-to")))
             ((eq elem 'reply-to)
-             (let ((from (mail-fetch-field "from"))
-                   (reply-to (mail-fetch-field "reply-to")))
+             (let ((from (message-fetch-field "from"))
+                   (reply-to (message-fetch-field "reply-to")))
                (when (and
                       from reply-to
                       (equal 
-                       (nth 1 (mail-extract-address-components from))
-                       (nth 1 (mail-extract-address-components reply-to))))
+                       (nth 1 (funcall gnus-extract-address-components from))
+                       (nth 1 (funcall gnus-extract-address-components
+                                       reply-to))))
                  (gnus-article-hide-header "reply-to"))))
             ((eq elem 'date)
-             (let ((date (mail-fetch-field "date")))
+             (let ((date (message-fetch-field "date")))
                (when (and date
                           (< (gnus-days-between date (current-time-string))
                              4))
@@ -13338,15 +14071,14 @@ always hide."
   (save-excursion
     (goto-char (point-min))
     (when (re-search-forward (concat "^" header ":") nil t)
-      (add-text-properties
+      (gnus-hide-text-type
        (progn (beginning-of-line) (point))
        (progn 
         (end-of-line)
         (if (re-search-forward "^[^ \t]" nil t)
             (match-beginning 0)
           (point-max)))
-       (nconc (list 'gnus-type 'boring-headers)
-             gnus-hidden-properties)))))
+       'boring-headers))))
 
 ;; Written by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defun gnus-article-treat-overstrike ()
@@ -13358,25 +14090,25 @@ always hide."
       (while (search-forward "\b" nil t)
        (let ((next (following-char))
              (previous (char-after (- (point) 2))))
-         (cond ((eq next previous)
-                (put-text-property (- (point) 2) (point) 'invisible t)
-                (put-text-property (point) (1+ (point)) 'face 'bold))
-               ((eq next ?_)
-                (put-text-property (1- (point)) (1+ (point)) 'invisible t)
-                (put-text-property
-                 (- (point) 2) (1- (point)) 'face 'underline))
-               ((eq previous ?_)
-                (put-text-property (- (point) 2) (point) 'invisible t)
-                (put-text-property
-                 (point) (1+ (point))  'face 'underline))))))))
+         (cond 
+          ((eq next previous)
+           (gnus-put-text-property (- (point) 2) (point) 'invisible t)
+           (gnus-put-text-property (point) (1+ (point)) 'face 'bold))
+          ((eq next ?_)
+           (gnus-put-text-property (1- (point)) (1+ (point)) 'invisible t)
+           (gnus-put-text-property
+            (- (point) 2) (1- (point)) 'face 'underline))
+          ((eq previous ?_)
+           (gnus-put-text-property (- (point) 2) (point) 'invisible t)
+           (gnus-put-text-property
+            (point) (1+ (point))       'face 'underline))))))))
 
 (defun gnus-article-word-wrap ()
   "Format too long lines."
   (interactive)
   (save-excursion
     (set-buffer gnus-article-buffer)
-    (let ((buffer-read-only nil)
-         p)
+    (let ((buffer-read-only nil))
       (widen)
       (goto-char (point-min))
       (search-forward "\n\n" nil t)
@@ -13428,7 +14160,7 @@ always hide."
          from)
       (save-restriction
        (nnheader-narrow-to-headers)
-       (setq from (mail-fetch-field "from"))
+       (setq from (message-fetch-field "from"))
        (goto-char (point-min))
        (when (and gnus-article-x-face-command
                   (or force
@@ -13453,25 +14185,33 @@ always hide."
              (let ((process-connection-type nil))
                (process-kill-without-query
                 (start-process
-                 "gnus-x-face" nil "sh" "-c" gnus-article-x-face-command))
+                 "gnus-x-face" nil shell-file-name shell-command-switch
+                 gnus-article-x-face-command))
                (process-send-region "gnus-x-face" beg end)
                (process-send-eof "gnus-x-face")))))))))
 
-(defun gnus-headers-decode-quoted-printable ()
+(defalias 'gnus-headers-decode-quoted-printable 'gnus-decode-rfc1522)
+(defun gnus-decode-rfc1522 ()
   "Hack to remove QP encoding from headers."
   (let ((case-fold-search t)
        (inhibit-point-motion-hooks t)
+       (buffer-read-only nil)
        string)
-    (goto-char (point-min))
-    (while (re-search-forward "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
-      (setq string (match-string 1))
-      (narrow-to-region (match-beginning 0) (match-end 0))
-      (delete-region (point-min) (point-max))
-      (insert string)
-      (gnus-mime-decode-quoted-printable (goto-char (point-min)) (point-max))
-      (subst-char-in-region (point-min) (point-max) ?_ ? )
-      (widen)
-      (goto-char (point-min)))))
+    (save-restriction
+      (narrow-to-region
+       (goto-char (point-min))
+       (or (search-forward "\n\n" nil t) (point-max)))
+
+      (while (re-search-forward 
+             "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
+       (setq string (match-string 1))
+       (narrow-to-region (match-beginning 0) (match-end 0))
+       (delete-region (point-min) (point-max))
+       (insert string)
+       (gnus-mime-decode-quoted-printable (goto-char (point-min)) (point-max))
+       (subst-char-in-region (point-min) (point-max) ?_ ? )
+       (widen)
+       (goto-char (point-min))))))
 
 (defun gnus-article-de-quoted-unreadable (&optional force)
   "Do a naive translation of a quoted-printable-encoded article.
@@ -13486,24 +14226,26 @@ or not."
     (let ((case-fold-search t)
          (buffer-read-only nil)
          (type (gnus-fetch-field "content-transfer-encoding")))
+      (gnus-decode-rfc1522)
       (when (or force
-               (and type (string-match "quoted-printable" type)))
+               (and type (string-match "quoted-printable" (downcase type))))
        (goto-char (point-min))
        (search-forward "\n\n" nil 'move)
-       (gnus-mime-decode-quoted-printable (point) (point-max))
-       (gnus-headers-decode-quoted-printable)))))
+       (gnus-mime-decode-quoted-printable (point) (point-max))))))
 
 (defun gnus-mime-decode-quoted-printable (from to)
   "Decode Quoted-Printable in the region between FROM and TO."
+  (interactive "r")
   (goto-char from)
   (while (search-forward "=" to t)
     (cond ((eq (following-char) ?\n)
           (delete-char -1)
           (delete-char 1))
          ((looking-at "[0-9A-F][0-9A-F]")
-          (delete-char -1)
-          (insert (hexl-hex-string-to-integer
-                   (buffer-substring (point) (+ 2 (point)))))
+          (subst-char-in-region
+           (1- (point)) (point) ?=
+           (hexl-hex-string-to-integer
+            (buffer-substring (point) (+ 2 (point)))))
           (delete-char 2))
          ((looking-at "=")
           (delete-char 1))
@@ -13513,7 +14255,7 @@ or not."
   "Toggle hiding of any PGP headers and signatures in the current article.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive "P")
+  (interactive (gnus-hidden-arg))
   (unless (gnus-article-check-hidden-text 'pgp arg)
     (save-excursion
       (set-buffer gnus-article-buffer)
@@ -13523,13 +14265,13 @@ always hide."
        (goto-char (point-min))
        ;; Hide the "header".
        (and (search-forward "\n-----BEGIN PGP SIGNED MESSAGE-----\n" nil t)
-            (add-text-properties (match-beginning 0) (match-end 0) props))
+            (gnus-hide-text (match-beginning 0) (match-end 0) props))
        (setq beg (point))
        ;; Hide the actual signature.
        (and (search-forward "\n-----BEGIN PGP SIGNATURE-----\n" nil t)
-            (setq end (match-beginning 0))
-            (add-text-properties
-             (match-beginning 0)
+            (setq end (1+ (match-beginning 0)))
+            (gnus-hide-text
+             end
              (if (search-forward "\n-----END PGP SIGNATURE-----\n" nil t)
                  (match-end 0)
                ;; Perhaps we shouldn't hide to the end of the buffer
@@ -13541,36 +14283,46 @@ always hide."
          (narrow-to-region beg end)
          (goto-char (point-min))
          (while (re-search-forward "^- " nil t)
-           (add-text-properties (match-beginning 0) (match-end 0) props))
+           (gnus-hide-text (match-beginning 0) (match-end 0) props))
          (widen))))))
 
 (defun gnus-article-hide-signature (&optional arg)
   "Hide the signature in the current article.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
-  (interactive "P")
+  (interactive (gnus-hidden-arg))
   (unless (gnus-article-check-hidden-text 'signature arg)
     (save-excursion
       (set-buffer gnus-article-buffer)
       (save-restriction
        (let ((buffer-read-only nil))
          (when (gnus-narrow-to-signature)
-           (add-text-properties
-            (point-min) (point-max)
-            (nconc (list 'gnus-type 'signature)
-                   gnus-hidden-properties))))))))
+           (gnus-hide-text-type (point-min) (point-max) 'signature)))))))
 
-(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.")
+(defun gnus-article-strip-leading-blank-lines ()
+  "Remove all blank lines from the beginning of the article."
+  (interactive)
+  (save-excursion
+    (set-buffer gnus-article-buffer)
+    (let (buffer-read-only)
+      (goto-char (point-min))
+      (when (search-forward "\n\n" nil t)
+       (while (looking-at "[ \t]$")
+         (gnus-delete-line))))))
 
+(defvar mime::preview/content-list)
+(defvar mime::preview-content-info/point-min)
 (defun gnus-narrow-to-signature ()
   "Narrow to the signature."
   (widen)
+  (if (and (boundp 'mime::preview/content-list)
+          mime::preview/content-list)
+      (let ((pcinfo (car (last mime::preview/content-list))))
+       (condition-case ()
+           (narrow-to-region
+            (funcall (intern "mime::preview-content-info/point-min") pcinfo)
+            (point-max))
+         (error nil))))
   (goto-char (point-max))
   (when (re-search-backward gnus-signature-separator nil t)
     (forward-line 1)
@@ -13584,22 +14336,33 @@ matches, the text in question is not a signature.")
       (narrow-to-region (point) (point-max))
       t)))
 
+(defun gnus-hidden-arg ()
+  "Return the current prefix arg as a number, or 0 if no prefix."
+  (list (if current-prefix-arg
+           (prefix-numeric-value current-prefix-arg)
+         0)))
+
 (defun gnus-article-check-hidden-text (type arg)
-  "Return nil if hiding is necessary."
+  "Return nil if hiding is necessary.
+Arg can be nil or a number.  Nil and positive means hide, negative
+means show, 0 means toggle."
   (save-excursion
     (set-buffer gnus-article-buffer)
     (let ((hide (gnus-article-hidden-text-p type)))
-      (cond ((or (and (null arg) (eq hide 'hidden))
-                (and arg (< 0 (prefix-numeric-value arg))))
-            (gnus-article-show-hidden-text type))
-           ((eq hide 'shown)
-            (gnus-article-show-hidden-text type t))
-           (t nil)))))
+      (cond
+       ((or (null arg)
+           (> arg 0))
+       nil)
+       ((< arg 0)
+       (gnus-article-show-hidden-text type))
+       (t
+       (if (eq hide 'hidden)
+           (gnus-article-show-hidden-text type)
+         nil))))))
 
 (defun gnus-article-hidden-text-p (type)
   "Say whether the current buffer contains hidden text of type TYPE."
-  (let ((pos (text-property-any (point-min) (point-max) 'gnus-type type))
-       prop)
+  (let ((pos (text-property-any (point-min) (point-max) 'gnus-type type)))
     (when pos
       (if (get-text-property pos 'invisible)
          'hidden
@@ -13623,14 +14386,15 @@ If HIDE, hide the text instead."
     (set-buffer gnus-article-buffer)
     (let ((buffer-read-only nil)
          (inhibit-point-motion-hooks t)
-         (beg (point)))
+         (beg (point-min)))
       (while (gnus-goto-char (text-property-any
                              beg (point-max) 'gnus-type type))
+       (setq beg (point))
+       (forward-char)
        (if hide
-           (add-text-properties (point) (setq beg (1+ (point)))
-                                gnus-hidden-properties)
-         (remove-text-properties (point) (setq beg (1+ (point)))
-                                 gnus-hidden-properties)))
+           (gnus-hide-text beg (point) gnus-hidden-properties)
+         (gnus-unhide-text beg (point)))
+       (setq beg (point)))
       t)))
 
 (defvar gnus-article-time-units
@@ -13652,7 +14416,8 @@ how much time has lapsed since DATE."
         (date (and (vectorp header) (mail-header-date header)))
         (date-regexp "^Date: \\|^X-Sent: ")
         (now (current-time))
-        (inhibit-point-motion-hooks t))
+        (inhibit-point-motion-hooks t)
+        bface eface)
     (when (and date (not (string= date "")))
       (save-excursion
        (set-buffer gnus-article-buffer)
@@ -13660,83 +14425,101 @@ how much time has lapsed since DATE."
          (nnheader-narrow-to-headers)
          (let ((buffer-read-only nil))
            ;; Delete any old Date headers.
-           (if (zerop (nnheader-remove-header date-regexp t))
-               (beginning-of-line)
+           (if (re-search-forward date-regexp nil t)
+               (progn
+                 (setq bface (get-text-property (gnus-point-at-bol) 'face)
+                       eface (get-text-property (1- (gnus-point-at-eol))
+                                                'face))
+                 (message-remove-header date-regexp t)
+                 (beginning-of-line))
              (goto-char (point-max)))
-           (insert
-            (cond
-             ;; Convert to the local timezone.  We have to slap a
-             ;; `condition-case' round the calls to the timezone
-             ;; functions since they aren't particularly resistant to
-             ;; buggy dates.
-             ((eq type 'local)
-              (concat "Date: " (condition-case ()
-                                   (timezone-make-date-arpa-standard date)
-                                 (error date))
-                      "\n"))
-             ;; Convert to Universal Time.
-             ((eq type 'ut)
-              (concat "Date: "
-                      (condition-case ()
-                          (timezone-make-date-arpa-standard date nil "UT")
-                        (error date))
-                      "\n"))
-             ;; Get the original date from the article.
-             ((eq type 'original)
-              (concat "Date: " date "\n"))
-             ;; Do an X-Sent lapsed format.
-             ((eq type 'lapsed)
-              ;; If the date is seriously mangled, the timezone
-              ;; functions are liable to bug out, so we condition-case
-              ;; the entire thing.
-              (let* ((real-time
-                      (condition-case ()
-                          (gnus-time-minus
-                           (gnus-encode-date
-                            (timezone-make-date-arpa-standard
-                             (current-time-string now)
-                             (current-time-zone now) "UT"))
-                           (gnus-encode-date
-                            (timezone-make-date-arpa-standard
-                             date nil "UT")))
-                        (error '(0 0))))
-                     (real-sec (+ (* (float (car real-time)) 65536)
-                                  (cadr real-time)))
-                     (sec (abs real-sec))
-                     num prev)
-                (if (zerop sec)
-                    "X-Sent: Now\n"
-                  (concat
-                   "X-Sent: "
-                   ;; This is a bit convoluted, but basically we go
-                   ;; through the time units for years, weeks, etc,
-                   ;; and divide things to see whether that results
-                   ;; in positive answers.
-                   (mapconcat
-                    (lambda (unit)
-                      (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
-                          ;; The (remaining) seconds are too few to
-                          ;; be divided into this time unit.
-                          ""
-                        ;; It's big enough, so we output it.
-                        (setq sec (- sec (* num (cdr unit))))
-                        (prog1
-                            (concat (if prev ", " "") (int-to-string
-                                                       (floor num))
-                                    " " (symbol-name (car unit))
-                                    (if (> num 1) "s" ""))
-                          (setq prev t))))
-                    gnus-article-time-units "")
-                   ;; If dates are odd, then it might appear like the
-                   ;; article was sent in the future.
-                   (if (> real-sec 0)
-                       " ago\n"
-                     " in the future\n")))))
-             (t
-              (error "Unknown conversion type: %s" type)))))
-         ;; Do highlighting.
-         (when (and highlight (gnus-visual-p 'article-highlight 'highlight))
-           (gnus-article-highlight-headers)))))))
+           (insert (gnus-make-date-line date type))
+           ;; Do highlighting.
+           (forward-line -1)
+           (when (and (gnus-visual-p 'article-highlight 'highlight)
+                      (looking-at "\\([^:]+\\): *\\(.*\\)$"))
+             (gnus-put-text-property (match-beginning 1) (match-end 1)
+                                'face bface)
+             (gnus-put-text-property (match-beginning 2) (match-end 2)
+                                'face eface))))))))
+
+(defun gnus-make-date-line (date type)
+  "Return a DATE line of TYPE."
+  (cond
+   ;; Convert to the local timezone.  We have to slap a
+   ;; `condition-case' round the calls to the timezone
+   ;; functions since they aren't particularly resistant to
+   ;; buggy dates.
+   ((eq type 'local)
+    (concat "Date: " (condition-case ()
+                        (timezone-make-date-arpa-standard date)
+                      (error date))
+           "\n"))
+   ;; Convert to Universal Time.
+   ((eq type 'ut)
+    (concat "Date: "
+           (condition-case ()
+               (timezone-make-date-arpa-standard date nil "UT")
+             (error date))
+           "\n"))
+   ;; Get the original date from the article.
+   ((eq type 'original)
+    (concat "Date: " date "\n"))
+   ;; Do an X-Sent lapsed format.
+   ((eq type 'lapsed)
+    ;; If the date is seriously mangled, the timezone
+    ;; functions are liable to bug out, so we condition-case
+    ;; the entire thing.
+    (let* ((now (current-time))
+          (real-time
+           (condition-case ()
+               (gnus-time-minus
+                (gnus-encode-date
+                 (timezone-make-date-arpa-standard
+                  (current-time-string now)
+                  (current-time-zone now) "UT"))
+                (gnus-encode-date
+                 (timezone-make-date-arpa-standard
+                  date nil "UT")))
+             (error '(0 0))))
+          (real-sec (+ (* (float (car real-time)) 65536)
+                       (cadr real-time)))
+          (sec (abs real-sec))
+          num prev)
+      (cond
+       ((equal real-time '(0 0))
+       "X-Sent: Unknown\n")
+       ((zerop sec)
+       "X-Sent: Now\n")
+       (t
+       (concat
+        "X-Sent: "
+        ;; This is a bit convoluted, but basically we go
+        ;; through the time units for years, weeks, etc,
+        ;; and divide things to see whether that results
+        ;; in positive answers.
+        (mapconcat
+         (lambda (unit)
+           (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
+               ;; The (remaining) seconds are too few to
+               ;; be divided into this time unit.
+               ""
+             ;; It's big enough, so we output it.
+             (setq sec (- sec (* num (cdr unit))))
+             (prog1
+                 (concat (if prev ", " "") (int-to-string
+                                            (floor num))
+                         " " (symbol-name (car unit)) 
+                         (if (> num 1) "s" ""))
+               (setq prev t))))
+         gnus-article-time-units "")
+        ;; If dates are odd, then it might appear like the
+        ;; article was sent in the future.
+        (if (> real-sec 0)
+            " ago\n"
+          " in the future\n"))))))
+   (t
+    (error "Unknown conversion type: %s" type))))
 
 (defun gnus-article-date-local (&optional highlight)
   "Convert the current article date to the local timezone."
@@ -13760,7 +14543,7 @@ function and want to see what the date was before converting."
   (if (gnus-visual-p 'article-highlight 'highlight)
       (gnus-article-highlight-some)))
 
-;; Article savers.
+;;; Article savers.
 
 (defun gnus-output-to-rmail (file-name)
   "Append the current article to an Rmail file named FILE-NAME."
@@ -13815,20 +14598,14 @@ function and want to see what the date was before converting."
 
 (defun gnus-output-to-file (file-name)
   "Append the current article to a file named FILE-NAME."
-  (setq file-name (expand-file-name file-name))
-  (let ((artbuf (current-buffer))
-       (tmpbuf (get-buffer-create " *Gnus-output*")))
-    (save-excursion
-      (set-buffer tmpbuf)
-      (buffer-disable-undo (current-buffer))
-      (erase-buffer)
+  (let ((artbuf (current-buffer)))
+    (nnheader-temp-write nil
       (insert-buffer-substring artbuf)
       ;; Append newline at end of the buffer as separator, and then
       ;; save it to file.
       (goto-char (point-max))
       (insert "\n")
-      (append-to-file (point-min) (point-max) file-name))
-    (kill-buffer tmpbuf)))
+      (append-to-file (point-min) (point-max) file-name))))
 
 (defun gnus-convert-article-to-rmail ()
   "Convert article in current buffer to Rmail message format."
@@ -13877,19 +14654,18 @@ If given a numerical ARG, move forward ARG pages."
        (goto-char (point-max))
        (gnus-insert-next-page-button)))))
 
-
 ;; Article mode commands
 
 (defun gnus-article-goto-next-page ()
   "Show the next page of the article."
   (interactive)
   (when (gnus-article-next-page)
-    (gnus-article-read-summary-keys nil ?n)))
+    (gnus-article-read-summary-keys nil (gnus-character-to-event ?n))))
 
 (defun gnus-article-goto-prev-page ()
   "Show the next page of the article."
   (interactive)
-  (if (bobp) (gnus-article-read-summary-keys nil ?n)
+  (if (bobp) (gnus-article-read-summary-keys nil (gnus-character-to-event ?n))
     (gnus-article-prev-page nil)))
 
 (defun gnus-article-next-page (&optional lines)
@@ -13917,6 +14693,7 @@ Argument LINES specifies lines to be scrolled up."
       (end-of-buffer
        ;; Long lines may cause an end-of-buffer error.
        (goto-char (point-max))))
+    (move-to-window-line 0)
     nil))
 
 (defun gnus-article-prev-page (&optional lines)
@@ -13931,9 +14708,11 @@ Argument LINES specifies lines to be scrolled down."
        (gnus-narrow-to-page -1)        ;Go to previous page.
        (goto-char (point-max))
        (recenter -1))
-    (condition-case ()
-       (scroll-down lines)
-      (error nil))))
+    (prog1
+       (condition-case ()
+           (scroll-down lines)
+         (error nil))
+      (move-to-window-line 0))))
 
 (defun gnus-article-refer-article ()
   "Read article specified by message-id around point."
@@ -13987,7 +14766,7 @@ Argument LINES specifies lines to be scrolled down."
   (let ((nosaves
         '("q" "Q"  "c" "r" "R" "\C-c\C-f" "m"  "a" "f" "F"
           "Zc" "ZC" "ZE" "ZQ" "ZZ" "Zn" "ZR" "ZG" "ZN" "ZP"
-          "=" "^" "\M-^"))
+          "=" "^" "\M-^" "|"))
        keys)
     (save-excursion
       (set-buffer gnus-summary-buffer)
@@ -14019,7 +14798,9 @@ Argument LINES specifies lines to be scrolled down."
          (set-window-point (get-buffer-window (current-buffer)) opoint))))))
 
 \f
-;; Basic ideas by emv@math.lsa.umich.edu (Edward Vielmetti)
+;;;
+;;; Kill file handling.
+;;;
 
 ;;;###autoload
 (defalias 'gnus-batch-kill 'gnus-batch-score)
@@ -14051,7 +14832,7 @@ score the alt hierarchy, you'd say \"!alt.all\"."
     ;; Apply kills to specified newsgroups in command line arguments.
     (setq newsrc (cdr gnus-newsrc-alist))
     (while newsrc
-      (setq group (car (car newsrc)))
+      (setq group (caar newsrc))
       (setq entry (gnus-gethash group gnus-newsrc-hashtb))
       (if (and (<= (nth 1 (car newsrc)) gnus-level-subscribed)
               (and (car entry)
@@ -14077,13 +14858,12 @@ Returns the number of articles marked as read."
     0))
 
 (defun gnus-kill-save-kill-buffer ()
-  (save-excursion
-    (let ((file (gnus-newsgroup-kill-file gnus-newsgroup-name)))
-      (if (get-file-buffer file)
-         (progn
-           (set-buffer (get-file-buffer file))
-           (and (buffer-modified-p) (save-buffer))
-           (kill-buffer (current-buffer)))))))
+  (let ((file (gnus-newsgroup-kill-file gnus-newsgroup-name)))
+    (when (get-file-buffer file)
+      (save-excursion
+       (set-buffer (get-file-buffer file))
+       (and (buffer-modified-p) (save-buffer))
+       (kill-buffer (current-buffer))))))
 
 (defvar gnus-kill-file-name "KILL"
   "Suffix of the kill files.")
@@ -14091,21 +14871,22 @@ Returns the number of articles marked as read."
 (defun gnus-newsgroup-kill-file (newsgroup)
   "Return the name of a kill file name for NEWSGROUP.
 If NEWSGROUP is nil, return the global kill file name instead."
-  (cond ((or (null newsgroup)
-            (string-equal newsgroup ""))
-        ;; The global KILL file is placed at top of the directory.
-        (expand-file-name gnus-kill-file-name
-                          (or gnus-kill-files-directory "~/News")))
-       ((gnus-use-long-file-name 'not-kill)
-        ;; Append ".KILL" to newsgroup name.
-        (expand-file-name (concat (gnus-newsgroup-savable-name newsgroup)
-                                  "." gnus-kill-file-name)
-                          (or gnus-kill-files-directory "~/News")))
-       (t
-        ;; Place "KILL" under the hierarchical directory.
-        (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
-                                  "/" gnus-kill-file-name)
-                          (or gnus-kill-files-directory "~/News")))))
+  (cond 
+   ;; The global KILL file is placed at top of the directory.
+   ((or (null newsgroup)
+       (string-equal newsgroup ""))
+    (expand-file-name gnus-kill-file-name
+                     gnus-kill-files-directory))
+   ;; Append ".KILL" to newsgroup name.
+   ((gnus-use-long-file-name 'not-kill)
+    (expand-file-name (concat (gnus-newsgroup-savable-name newsgroup)
+                             "." gnus-kill-file-name)
+                     gnus-kill-files-directory))
+   ;; Place "KILL" under the hierarchical directory.
+   (t
+    (expand-file-name (concat (gnus-newsgroup-directory-form newsgroup)
+                             "/" gnus-kill-file-name)
+                     gnus-kill-files-directory))))
 
 \f
 ;;;
@@ -14150,7 +14931,8 @@ If NEWSGROUP is nil, return the global kill file name instead."
       (bury-buffer (current-buffer))
       (set-buffer-modified-p nil)
       (let ((auto (make-auto-save-file-name))
-           (gnus-dribble-ignore t))
+           (gnus-dribble-ignore t)
+           modes)
        (when (or (file-exists-p auto) (file-exists-p dribble-file))
          ;; Load whichever file is newest -- the auto save file
          ;; or the "real" file.
@@ -14161,17 +14943,16 @@ If NEWSGROUP is nil, return the global kill file name instead."
            (set-buffer-modified-p t))
          ;; Set the file modes to reflect the .newsrc file modes.
          (save-buffer)
-         (when (file-exists-p gnus-current-startup-file)
-           (set-file-modes dribble-file
-                           (file-modes gnus-current-startup-file)))
+         (when (and (file-exists-p gnus-current-startup-file)
+                    (setq modes (file-modes gnus-current-startup-file)))
+           (set-file-modes dribble-file modes))
          ;; Possibly eval the file later.
          (when (gnus-y-or-n-p
                 "Auto-save file exists.  Do you want to read it? ")
            (setq gnus-dribble-eval-file t)))))))
 
 (defun gnus-dribble-eval-file ()
-  (if (not gnus-dribble-eval-file)
-      ()
+  (when gnus-dribble-eval-file
     (setq gnus-dribble-eval-file nil)
     (save-excursion
       (let ((gnus-dribble-ignore t))
@@ -14179,33 +14960,33 @@ If NEWSGROUP is nil, return the global kill file name instead."
        (eval-buffer (current-buffer))))))
 
 (defun gnus-dribble-delete-file ()
-  (if (file-exists-p (gnus-dribble-file-name))
-      (delete-file (gnus-dribble-file-name)))
-  (if gnus-dribble-buffer
-      (save-excursion
-       (set-buffer gnus-dribble-buffer)
-       (let ((auto (make-auto-save-file-name)))
-         (if (file-exists-p auto)
-             (delete-file auto))
-         (erase-buffer)
-         (set-buffer-modified-p nil)))))
+  (when (file-exists-p (gnus-dribble-file-name))
+    (delete-file (gnus-dribble-file-name)))
+  (when gnus-dribble-buffer
+    (save-excursion
+      (set-buffer gnus-dribble-buffer)
+      (let ((auto (make-auto-save-file-name)))
+       (if (file-exists-p auto)
+           (delete-file auto))
+       (erase-buffer)
+       (set-buffer-modified-p nil)))))
 
 (defun gnus-dribble-save ()
-  (if (and gnus-dribble-buffer
-          (buffer-name gnus-dribble-buffer))
-      (save-excursion
-       (set-buffer gnus-dribble-buffer)
-       (save-buffer))))
+  (when (and gnus-dribble-buffer
+            (buffer-name gnus-dribble-buffer))
+    (save-excursion
+      (set-buffer gnus-dribble-buffer)
+      (save-buffer))))
 
 (defun gnus-dribble-clear ()
-  (save-excursion
-    (if (gnus-buffer-exists-p gnus-dribble-buffer)
-       (progn
-         (set-buffer gnus-dribble-buffer)
-         (erase-buffer)
-         (set-buffer-modified-p nil)
-         (setq buffer-saved-size (buffer-size))))))
+  (when (gnus-buffer-exists-p gnus-dribble-buffer)
+    (save-excursion
+      (set-buffer gnus-dribble-buffer)
+      (erase-buffer)
+      (set-buffer-modified-p nil)
+      (setq buffer-saved-size (buffer-size)))))
 
+\f
 ;;;
 ;;; Server Communication
 ;;;
@@ -14267,11 +15048,8 @@ If CONFIRM is non-nil, the user will be asked for an NNTP server."
         "%s (%s) open error: '%s'.     Continue? "
         (car gnus-select-method) (cadr gnus-select-method)
         (gnus-status-message gnus-select-method)))
-       (progn
-        (gnus-message 1 "Couldn't open server on %s"
-                      (nth 1 gnus-select-method))
-        (ding)
-        nil)))))
+       (gnus-error 1 "Couldn't open server on %s"
+                  (nth 1 gnus-select-method))))))
 
 (defun gnus-check-group (group)
   "Try to make sure that the server where GROUP exists is alive."
@@ -14279,7 +15057,7 @@ If CONFIRM is non-nil, the user will be asked for an NNTP server."
     (or (gnus-server-opened method)
        (gnus-open-server method))))
 
-(defun gnus-check-server (&optional method)
+(defun gnus-check-server (&optional method silent)
   "Check whether the connection to METHOD is down.
 If METHOD is nil, use `gnus-select-method'.
 If it is down, start it up (again)."
@@ -14291,13 +15069,17 @@ If it is down, start it up (again)."
        ;; The stream is already opened.
        t
       ;; Open the server.
-      (gnus-message 5 "Opening %s server on %s..." (car method) (nth 1 method))
+      (unless silent
+       (gnus-message 5 "Opening %s server%s..." (car method)
+                     (if (equal (nth 1 method) "") ""
+                       (format " on %s" (nth 1 method)))))
       (run-hooks 'gnus-open-server-hook)
       (prog1
          (gnus-open-server method)
-       (message "")))))
+       (unless silent
+         (message ""))))))
 
-(defun gnus-get-function (method function)
+(defun gnus-get-function (method function &optional noerror)
   "Return a function symbol based on METHOD and FUNCTION."
   ;; Translate server names into methods.
   (unless method
@@ -14309,15 +15091,21 @@ If it is down, start it up (again)."
     ;; question.
     (unless (fboundp func)
       (require (car method))
-      (unless (fboundp func)
+      (when (and (not (fboundp func))
+                (not noerror))
        ;; This backend doesn't implement this function.
        (error "No such function: %s" func)))
     func))
 
+\f
+;;;
 ;;; Interface functions to the backends.
+;;;
 
 (defun gnus-open-server (method)
   "Open a connection to METHOD."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (let ((elem (assoc method gnus-opened-servers)))
     ;; If this method was previously denied, we just return nil.
     (if (eq (nth 1 elem) 'denied)
@@ -14339,23 +15127,33 @@ If it is down, start it up (again)."
 
 (defun gnus-close-server (method)
   "Close the connection to METHOD."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (funcall (gnus-get-function method 'close-server) (nth 1 method)))
 
 (defun gnus-request-list (method)
   "Request the active file from METHOD."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (funcall (gnus-get-function method 'request-list) (nth 1 method)))
 
 (defun gnus-request-list-newsgroups (method)
   "Request the newsgroups file from METHOD."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (funcall (gnus-get-function method 'request-list-newsgroups) (nth 1 method)))
 
 (defun gnus-request-newgroups (date method)
   "Request all new groups since DATE from METHOD."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (funcall (gnus-get-function method 'request-newgroups)
           date (nth 1 method)))
 
 (defun gnus-server-opened (method)
   "Check whether a connection to METHOD has been opened."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (funcall (gnus-get-function method 'server-opened) (nth 1 method)))
 
 (defun gnus-status-message (method)
@@ -14369,6 +15167,8 @@ this group uses will be queried."
 (defun gnus-request-group (group &optional dont-check method)
   "Request GROUP.  If DONT-CHECK, no information is required."
   (let ((method (or method (gnus-find-method-for-group group))))
+    (when (stringp method)
+      (setq method (gnus-server-to-method method)))
     (funcall (gnus-get-function method 'request-group)
             (gnus-group-real-name group) (nth 1 method) dont-check)))
 
@@ -14413,6 +15213,8 @@ If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
 
 (defun gnus-retrieve-groups (groups method)
   "Request active information on GROUPS from METHOD."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (funcall (gnus-get-function method 'retrieve-groups) groups (nth 1 method)))
 
 (defun gnus-request-type (group &optional article)
@@ -14441,9 +15243,19 @@ If BUFFER, insert the article in that group."
 
 (defun gnus-request-head (article group)
   "Request the head of ARTICLE in GROUP."
-  (let ((method (gnus-find-method-for-group group)))
-    (funcall (gnus-get-function method 'request-head)
-            article (gnus-group-real-name group) (nth 1 method))))
+  (let* ((method (gnus-find-method-for-group group))
+        (head (gnus-get-function method 'request-head t)))
+    (if (fboundp head)
+       (funcall head article (gnus-group-real-name group) (nth 1 method))
+      (let ((res (gnus-request-article article group)))
+       (when res
+         (save-excursion
+           (set-buffer nntp-server-buffer)
+           (goto-char (point-min))
+           (when (search-forward "\n\n" nil t)
+             (delete-region (1- (point)) (point-max)))
+           (nnheader-fold-continuation-lines)))
+       res))))
 
 (defun gnus-request-body (article group)
   "Request the body of ARTICLE in GROUP."
@@ -14453,6 +15265,8 @@ If BUFFER, insert the article in that group."
 
 (defun gnus-request-post (method)
   "Post the current buffer using METHOD."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (funcall (gnus-get-function method 'request-post) (nth 1 method)))
 
 (defun gnus-request-scan (group method)
@@ -14464,6 +15278,8 @@ If GROUP is nil, all groups on METHOD are scanned."
 
 (defsubst gnus-request-update-info (info method)
   "Request that METHOD update INFO."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (when (gnus-check-backend-function 'request-update-info (car method))
     (funcall (gnus-get-function method 'request-update-info)
             (gnus-group-real-name (gnus-info-group info))
@@ -14482,15 +15298,20 @@ If GROUP is nil, all groups on METHOD are scanned."
             article (gnus-group-real-name group)
             (nth 1 method) accept-function last)))
 
-(defun gnus-request-accept-article (group &optional last method)
+(defun gnus-request-accept-article (group method &optional last)
   ;; Make sure there's a newline at the end of the article.
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
+  (when (and (not method)
+            (stringp group))
+    (setq method (gnus-group-name-to-method group)))
   (goto-char (point-max))
   (unless (bolp)
     (insert "\n"))
-  (let ((func (if (symbolp group) group
-               (car (or method (gnus-find-method-for-group group))))))
+  (let ((func (car (or method (gnus-find-method-for-group group)))))
     (funcall (intern (format "%s-request-accept-article" func))
             (if (stringp group) (gnus-group-real-name group) group)
+            (cadr method)
             last)))
 
 (defun gnus-request-replace-article (article group buffer)
@@ -14510,6 +15331,8 @@ If GROUP is nil, all groups on METHOD are scanned."
             article (gnus-group-real-name group) (nth 1 method))))
 
 (defun gnus-request-create-group (group &optional method)
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (let ((method (or method (gnus-find-method-for-group group))))
     (funcall (gnus-get-function method 'request-create-group)
             (gnus-group-real-name group) (nth 1 method))))
@@ -14533,6 +15356,8 @@ If GROUP is nil, all groups on METHOD are scanned."
 
 (defun gnus-method-option-p (method option)
   "Return non-nil if select METHOD has OPTION as a parameter."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (memq option (assoc (format "%s" (car method))
                      gnus-valid-select-methods)))
 
@@ -14548,6 +15373,16 @@ If GROUP is nil, all groups on METHOD are scanned."
     (setcar (cdr entry) (concat (nth 1 entry) "+" group))
     (nconc entry (cdr method))))
 
+(defun gnus-group-name-to-method (group)
+  "Return a select method suitable for GROUP."
+  (if (string-match ":" group)
+      (let ((server (substring group 0 (match-beginning 0))))
+       (if (string-match "\\+" server)
+           (list (intern (substring server 0 (match-beginning 0)))
+                 (substring server (match-end 0)))
+         (list (intern server) "")))
+    gnus-select-method))
+
 (defun gnus-find-method-for-group (group &optional info)
   "Find the select method that GROUP uses."
   (or gnus-override-method
@@ -14556,16 +15391,22 @@ If GROUP is nil, all groups on METHOD are scanned."
       (let ((info (or info (gnus-get-info group)))
            method)
        (if (or (not info)
-               (not (setq method (gnus-info-method info))))
-           (setq method gnus-select-method)
+               (not (setq method (gnus-info-method info)))
+               (equal method "native"))
+           gnus-select-method
          (setq method
                (cond ((stringp method)
                       (gnus-server-to-method method))
                      ((stringp (car method))
                       (gnus-server-extend-method group method))
                      (t
-                      method))))
-       (gnus-server-add-address method))))
+                      method)))
+         (cond ((equal (cadr method) "")
+                method)
+               ((null (cadr method))
+                (list (car method) ""))
+               (t
+                (gnus-server-add-address method)))))))
 
 (defun gnus-check-backend-function (func group)
   "Check whether GROUP supports function FUNC."
@@ -14583,21 +15424,28 @@ If GROUP is nil, all groups on METHOD are scanned."
       (setq valids (cdr valids)))
     outs))
 
+\f
 ;;;
 ;;; Active & Newsrc File Handling
 ;;;
 
-(defun gnus-setup-news (&optional rawfile level)
+(defun gnus-setup-news (&optional rawfile level dont-connect)
   "Setup news information.
 If RAWFILE is non-nil, the .newsrc file will also be read.
 If LEVEL is non-nil, the news will be set up at level LEVEL."
   (let ((init (not (and gnus-newsrc-alist gnus-active-hashtb (not rawfile)))))
-    ;; Clear some variables to re-initialize news information.
-    (if init (setq gnus-newsrc-alist nil
-                  gnus-active-hashtb nil))
 
-    ;; Read the newsrc file and create `gnus-newsrc-hashtb'.
-    (if init (gnus-read-newsrc-file rawfile))
+    (when init 
+      ;; Clear some variables to re-initialize news information.
+      (setq gnus-newsrc-alist nil
+           gnus-active-hashtb nil)
+      ;; Read the newsrc file and create `gnus-newsrc-hashtb'.
+      (gnus-read-newsrc-file rawfile))
+
+    (when (and (not (assoc "archive" gnus-server-alist))
+              gnus-message-archive-method)
+      (push (cons "archive" gnus-message-archive-method)
+           gnus-server-alist))
 
     ;; If we don't read the complete active file, we fill in the
     ;; hashtb here.
@@ -14623,13 +15471,30 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
     ;; Possibly eval the dribble file.
     (and init (or gnus-use-dribble-file gnus-slave) (gnus-dribble-eval-file))
 
+    ;; Slave Gnusii should then clear the dribble buffer.
+    (when (and init gnus-slave)
+      (gnus-dribble-clear))
+
     (gnus-update-format-specifications)
 
+    ;; See whether we need to read the description file.
+    (if (and (string-match "%[-,0-9]*D" gnus-group-line-format)
+            (not gnus-description-hashtb)
+            (not dont-connect)
+            gnus-read-active-file)
+       (gnus-read-all-descriptions-files))
+
     ;; Find new newsgroups and treat them.
-    (if (and init gnus-check-new-newsgroups gnus-read-active-file (not level)
+    (if (and init gnus-check-new-newsgroups (not level)
             (gnus-check-server gnus-select-method))
        (gnus-find-new-newsgroups))
 
+    ;; We might read in new NoCeM messages here.
+    (when (and gnus-use-nocem 
+              (not level)
+              (not dont-connect))
+      (gnus-nocem-scan-groups))
+
     ;; Find the number of unread articles in each non-dead group.
     (let ((gnus-read-active-file (and (not level) gnus-read-active-file)))
       (gnus-get-unread-articles level))
@@ -14653,13 +15518,17 @@ the server for new groups."
     (unless (gnus-check-first-time-used)
       (if (or (consp check)
              (eq check 'ask-server))
+         ;; Ask the server for new groups.
          (gnus-ask-server-for-new-groups)
+       ;; Go through the active hashtb and look for new groups.
        (let ((groups 0)
              group new-newsgroups)
          (gnus-message 5 "Looking for new newsgroups...")
-         (or gnus-have-read-active-file (gnus-read-active-file))
+         (unless gnus-have-read-active-file
+           (gnus-read-active-file))
          (setq gnus-newsrc-last-checked-date (current-time-string))
-         (if (not gnus-killed-hashtb) (gnus-make-hashtable-from-killed))
+         (unless gnus-killed-hashtb
+           (gnus-make-hashtable-from-killed))
          ;; Go though every newsgroup in `gnus-active-hashtb' and compare
          ;; with `gnus-newsrc-hashtb' and `gnus-killed-hashtb'.
          (mapatoms
@@ -14685,8 +15554,8 @@ the server for new groups."
                       (setq new-newsgroups (cons group new-newsgroups))
                     (funcall gnus-subscribe-newsgroup-method group)))))))
           gnus-active-hashtb)
-         (if new-newsgroups
-             (gnus-subscribe-hierarchical-interactive new-newsgroups))
+         (when new-newsgroups
+           (gnus-subscribe-hierarchical-interactive new-newsgroups))
          ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
          (if (> groups 0)
              (gnus-message 6 "%d new newsgroup%s arrived."
@@ -14716,15 +15585,16 @@ the server for new groups."
    (t
     (let ((regs gnus-newsrc-options-n))
       (while (and regs
-                 (not (string-match (car (car regs)) group)))
+                 (not (string-match (caar regs) group)))
        (setq regs (cdr regs)))
-      (and regs (cdr (car regs)))))))
+      (and regs (cdar regs))))))
 
 (defun gnus-ask-server-for-new-groups ()
   (let* ((date (or gnus-newsrc-last-checked-date (current-time-string)))
         (methods (cons gnus-select-method
-                       (cons
-                        gnus-message-archive-method
+                       (nconc
+                        (when gnus-message-archive-method
+                          (list "archive"))
                         (append
                          (and (consp gnus-check-new-newsgroups)
                               gnus-check-new-newsgroups)
@@ -14736,6 +15606,7 @@ the server for new groups."
     ;; Go through both primary and secondary select methods and
     ;; request new newsgroups.
     (while (setq method (gnus-server-get-method nil (pop methods)))
+      (setq new-newsgroups nil)
       (setq gnus-override-subscribe-method method)
       (when (and (gnus-check-server method)
                 (gnus-request-newgroups date method))
@@ -14744,36 +15615,37 @@ the server for new groups."
          (setq hashtb (gnus-make-hashtable 100))
          (set-buffer nntp-server-buffer)
          ;; Enter all the new groups into a hashtable.
-         (gnus-active-to-gnus-format method hashtb 'ignore)))
-      ;; Now all new groups from `method' are in `hashtb'.
-      (mapatoms
-       (lambda (group-sym)
-        (if (or (null (setq group (symbol-name group-sym)))
-                (null (symbol-value group-sym))
-                (gnus-gethash group gnus-newsrc-hashtb)
-                (member group gnus-zombie-list)
-                (member group gnus-killed-list))
-            ;; The group is already known.
-            ()
-          ;; Make this group active.
-          (when (symbol-value group-sym)
-            (gnus-set-active group (symbol-value group-sym)))
-          ;; Check whether we want it or not.
-          (let ((do-sub (gnus-matches-options-n group)))
-            (cond
-             ((eq do-sub 'subscribe)
-              (incf groups)
-              (gnus-sethash group group gnus-killed-hashtb)
-              (funcall gnus-subscribe-options-newsgroup-method group))
-             ((eq do-sub 'ignore)
-              nil)
-             (t
-              (incf groups)
-              (gnus-sethash group group gnus-killed-hashtb)
-              (if gnus-subscribe-hierarchical-interactive
-                  (push group new-newsgroups)
-                (funcall gnus-subscribe-newsgroup-method group)))))))
-       hashtb)
+         (gnus-active-to-gnus-format method hashtb 'ignore))
+       ;; Now all new groups from `method' are in `hashtb'.
+       (mapatoms
+        (lambda (group-sym)
+          (if (or (null (setq group (symbol-name group-sym)))
+                  (not (boundp group-sym))
+                  (null (symbol-value group-sym))
+                  (gnus-gethash group gnus-newsrc-hashtb)
+                  (member group gnus-zombie-list)
+                  (member group gnus-killed-list))
+              ;; The group is already known.
+              ()
+            ;; Make this group active.
+            (when (symbol-value group-sym)
+              (gnus-set-active group (symbol-value group-sym)))
+            ;; Check whether we want it or not.
+            (let ((do-sub (gnus-matches-options-n group)))
+              (cond
+               ((eq do-sub 'subscribe)
+                (incf groups)
+                (gnus-sethash group group gnus-killed-hashtb)
+                (funcall gnus-subscribe-options-newsgroup-method group))
+               ((eq do-sub 'ignore)
+                nil)
+               (t
+                (incf groups)
+                (gnus-sethash group group gnus-killed-hashtb)
+                (if gnus-subscribe-hierarchical-interactive
+                    (push group new-newsgroups)
+                  (funcall gnus-subscribe-newsgroup-method group)))))))
+        hashtb))
       (when new-newsgroups
        (gnus-subscribe-hierarchical-interactive new-newsgroups)))
     ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
@@ -14790,7 +15662,8 @@ the server for new groups."
          (file-exists-p (concat gnus-startup-file ".eld")))
       nil
     (gnus-message 6 "First time user; subscribing you to default groups")
-    (or gnus-have-read-active-file (gnus-read-active-file))
+    (unless (gnus-read-active-file-p)
+      (gnus-read-active-file))
     (setq gnus-newsrc-last-checked-date (current-time-string))
     (let ((groups gnus-default-subscribed-newsgroups)
          group)
@@ -14857,7 +15730,8 @@ the server for new groups."
        (setq entry (gnus-gethash entry gnus-newsrc-hashtb)))
     (if (and (not oldlevel)
             (consp entry))
-       (setq oldlevel (car (cdr (nth 2 entry)))))
+       (setq oldlevel (gnus-info-level (nth 2 entry)))
+      (setq oldlevel (or oldlevel 9)))
     (if (stringp previous)
        (setq previous (gnus-gethash previous gnus-newsrc-hashtb)))
 
@@ -14876,77 +15750,75 @@ the server for new groups."
       ;; If the group was killed, we remove it from the killed or zombie
       ;; list.  If not, and it is in fact going to be killed, we remove
       ;; it from the newsrc hash table and assoc.
-      (cond ((>= oldlevel gnus-level-zombie)
-            (if (= oldlevel gnus-level-zombie)
-                (setq gnus-zombie-list (delete group gnus-zombie-list))
-              (setq gnus-killed-list (delete group gnus-killed-list))))
-           (t
-            (if (and (>= level gnus-level-zombie)
-                     entry)
-                (progn
-                  (gnus-sethash (car (nth 2 entry)) nil gnus-newsrc-hashtb)
-                  (if (nth 3 entry)
-                      (setcdr (gnus-gethash (car (nth 3 entry))
-                                            gnus-newsrc-hashtb)
-                              (cdr entry)))
-                  (setcdr (cdr entry) (cdr (cdr (cdr entry))))))))
+      (cond
+       ((>= oldlevel gnus-level-zombie)
+       (if (= oldlevel gnus-level-zombie)
+           (setq gnus-zombie-list (delete group gnus-zombie-list))
+         (setq gnus-killed-list (delete group gnus-killed-list))))
+       (t
+       (if (and (>= level gnus-level-zombie)
+                entry)
+           (progn
+             (gnus-sethash (car (nth 2 entry)) nil gnus-newsrc-hashtb)
+             (if (nth 3 entry)
+                 (setcdr (gnus-gethash (car (nth 3 entry))
+                                       gnus-newsrc-hashtb)
+                         (cdr entry)))
+             (setcdr (cdr entry) (cdddr entry))))))
 
       ;; Finally we enter (if needed) the list where it is supposed to
       ;; go, and change the subscription level.  If it is to be killed,
       ;; we enter it into the killed or zombie list.
-      (cond ((>= level gnus-level-zombie)
-            ;; Remove from the hash table.
-            (gnus-sethash group nil gnus-newsrc-hashtb)
-            ;; We do not enter foreign groups into the list of dead
-            ;; groups.
-            (unless (gnus-group-foreign-p group)
-              (if (= level gnus-level-zombie)
-                  (setq gnus-zombie-list (cons group gnus-zombie-list))
-                (setq gnus-killed-list (cons group gnus-killed-list)))))
-           (t
-            ;; If the list is to be entered into the newsrc assoc, and
-            ;; it was killed, we have to create an entry in the newsrc
-            ;; hashtb format and fix the pointers in the newsrc assoc.
-            (if (>= oldlevel gnus-level-zombie)
-                (progn
-                  (if (listp entry)
-                      (progn
-                        (setq info (cdr entry))
-                        (setq num (car entry)))
-                    (setq active (gnus-active group))
-                    (setq num
-                          (if active (- (1+ (cdr active)) (car active)) t))
-                    ;; Check whether the group is foreign.  If so, the
-                    ;; foreign select method has to be entered into the
-                    ;; info.
-                    (let ((method (or gnus-override-subscribe-method
-                                      (gnus-group-method-name group))))
-                      (if (eq method gnus-select-method)
-                          (setq info (list group level nil))
-                        (setq info (list group level nil nil method)))))
-                  (or previous
-                      (setq previous
-                            (let ((p gnus-newsrc-alist))
-                              (while (cdr (cdr p))
-                                (setq p (cdr p)))
-                              p)))
-                  (setq entry (cons info (cdr (cdr previous))))
-                  (if (cdr previous)
-                      (progn
-                        (setcdr (cdr previous) entry)
-                        (gnus-sethash group (cons num (cdr previous))
-                                      gnus-newsrc-hashtb))
-                    (setcdr previous entry)
-                    (gnus-sethash group (cons num previous)
-                                  gnus-newsrc-hashtb))
-                  (if (cdr entry)
-                      (setcdr (gnus-gethash (car (car (cdr entry)))
-                                            gnus-newsrc-hashtb)
-                              entry)))
-              ;; It was alive, and it is going to stay alive, so we
-              ;; just change the level and don't change any pointers or
-              ;; hash table entries.
-              (setcar (cdr (car (cdr (cdr entry)))) level))))
+      (cond 
+       ((>= level gnus-level-zombie)
+       ;; Remove from the hash table.
+       (gnus-sethash group nil gnus-newsrc-hashtb)
+       ;; We do not enter foreign groups into the list of dead
+       ;; groups.
+       (unless (gnus-group-foreign-p group)
+         (if (= level gnus-level-zombie)
+             (setq gnus-zombie-list (cons group gnus-zombie-list))
+           (setq gnus-killed-list (cons group gnus-killed-list)))))
+       (t
+       ;; If the list is to be entered into the newsrc assoc, and
+       ;; it was killed, we have to create an entry in the newsrc
+       ;; hashtb format and fix the pointers in the newsrc assoc.
+       (if (< oldlevel gnus-level-zombie)
+           ;; It was alive, and it is going to stay alive, so we
+           ;; just change the level and don't change any pointers or
+           ;; hash table entries.
+           (setcar (cdaddr entry) level)
+         (if (listp entry)
+             (setq info (cdr entry)
+                   num (car entry))
+           (setq active (gnus-active group))
+           (setq num
+                 (if active (- (1+ (cdr active)) (car active)) t))
+           ;; Check whether the group is foreign.  If so, the
+           ;; foreign select method has to be entered into the
+           ;; info.
+           (let ((method (or gnus-override-subscribe-method
+                             (gnus-group-method group))))
+             (if (eq method gnus-select-method)
+                 (setq info (list group level nil))
+               (setq info (list group level nil nil method)))))
+         (unless previous
+           (setq previous
+                 (let ((p gnus-newsrc-alist))
+                   (while (cddr p)
+                     (setq p (cdr p)))
+                   p)))
+         (setq entry (cons info (cddr previous)))
+         (if (cdr previous)
+             (progn
+               (setcdr (cdr previous) entry)
+               (gnus-sethash group (cons num (cdr previous))
+                             gnus-newsrc-hashtb))
+           (setcdr previous entry)
+           (gnus-sethash group (cons num previous)
+                         gnus-newsrc-hashtb))
+         (when (cdr entry)
+           (setcdr (gnus-gethash (caadr entry) gnus-newsrc-hashtb) entry)))))
       (when gnus-group-change-level-function
        (funcall gnus-group-change-level-function group level oldlevel)))))
 
@@ -14962,9 +15834,9 @@ newsgroup."
   (let ((newsrc (cdr gnus-newsrc-alist))
        bogus group entry info)
     (gnus-message 5 "Checking bogus newsgroups...")
-    (unless gnus-have-read-active-file
+    (unless (gnus-read-active-file-p)
       (gnus-read-active-file))
-    (when (member gnus-select-method gnus-have-read-active-file)
+    (when (gnus-read-active-file-p)
       ;; Find all bogus newsgroup that are subscribed.
       (while newsrc
        (setq info (pop newsrc)
@@ -15007,6 +15879,93 @@ newsgroup."
       (setcdr killed (delete (car killed) (cdr killed)))
       (setq killed (cdr killed)))))
 
+;; We want to inline a function from gnus-cache, so we cheat here:
+(eval-when-compile
+  (provide 'gnus)
+  (require 'gnus-cache))
+
+(defun gnus-get-unread-articles-in-group (info active &optional update)
+  (when active
+    ;; Allow the backend to update the info in the group.
+    (when (and update 
+              (gnus-request-update-info
+               info (gnus-find-method-for-group (gnus-info-group info))))
+      (gnus-activate-group (gnus-info-group info) nil t))
+    (let* ((range (gnus-info-read info))
+          (num 0))
+      ;; If a cache is present, we may have to alter the active info.
+      (when (and gnus-use-cache info)
+       (inline (gnus-cache-possibly-alter-active 
+                (gnus-info-group info) active)))
+      ;; Modify the list of read articles according to what articles
+      ;; are available; then tally the unread articles and add the
+      ;; number to the group hash table entry.
+      (cond
+       ((zerop (cdr active))
+       (setq num 0))
+       ((not range)
+       (setq num (- (1+ (cdr active)) (car active))))
+       ((not (listp (cdr range)))
+       ;; Fix a single (num . num) range according to the
+       ;; active hash table.
+       ;; Fix by Carsten Bormann <cabo@Informatik.Uni-Bremen.DE>.
+       (and (< (cdr range) (car active)) (setcdr range (1- (car active))))
+       (and (> (cdr range) (cdr active)) (setcdr range (cdr active)))
+       ;; Compute number of unread articles.
+       (setq num (max 0 (- (cdr active) (- (1+ (cdr range)) (car range))))))
+       (t
+       ;; The read list is a list of ranges.  Fix them according to
+       ;; the active hash table.
+       ;; First peel off any elements that are below the lower
+       ;; active limit.
+       (while (and (cdr range)
+                   (>= (car active)
+                       (or (and (atom (cadr range)) (cadr range))
+                           (caadr range))))
+         (if (numberp (car range))
+             (setcar range
+                     (cons (car range)
+                           (or (and (numberp (cadr range))
+                                    (cadr range))
+                               (cdadr range))))
+           (setcdr (car range)
+                   (or (and (numberp (nth 1 range)) (nth 1 range))
+                       (cdadr range))))
+         (setcdr range (cddr range)))
+       ;; Adjust the first element to be the same as the lower limit.
+       (if (and (not (atom (car range)))
+                (< (cdar range) (car active)))
+           (setcdr (car range) (1- (car active))))
+       ;; Then we want to peel off any elements that are higher
+       ;; than the upper active limit.
+       (let ((srange range))
+         ;; Go past all legal elements.
+         (while (and (cdr srange)
+                     (<= (or (and (atom (cadr srange))
+                                  (cadr srange))
+                             (caadr srange)) (cdr active)))
+           (setq srange (cdr srange)))
+         (if (cdr srange)
+             ;; Nuke all remaining illegal elements.
+             (setcdr srange nil))
+
+         ;; Adjust the final element.
+         (if (and (not (atom (car srange)))
+                  (> (cdar srange) (cdr active)))
+             (setcdr (car srange) (cdr active))))
+       ;; Compute the number of unread articles.
+       (while range
+         (setq num (+ num (- (1+ (or (and (atom (car range)) (car range))
+                                     (cdar range)))
+                             (or (and (atom (car range)) (car range))
+                                 (caar range)))))
+         (setq range (cdr range)))
+       (setq num (max 0 (- (cdr active) num)))))
+      ;; Set the number of unread articles.
+      (when info
+       (setcar (gnus-gethash (gnus-info-group info) gnus-newsrc-hashtb) num))
+      num)))
+
 ;; Go though `gnus-newsrc-alist' and compare with `gnus-active-hashtb'
 ;; and compute how many unread articles there are in each group.
 (defun gnus-get-unread-articles (&optional level)
@@ -15021,13 +15980,12 @@ newsgroup."
                  gnus-activate-foreign-newsgroups)
                 (t 0))
           level))
-        info group active virtuals method fmethod)
+        info group active method)
     (gnus-message 5 "Checking new news...")
 
     (while newsrc
-      (setq info (car newsrc)
-           group (gnus-info-group info)
-           active (gnus-active group))
+      (setq active (gnus-active (setq group (gnus-info-group
+                                            (setq info (pop newsrc))))))
 
       ;; Check newsgroups.  If the user doesn't want to check them, or
       ;; they can't be checked (for instance, if the news server can't
@@ -15037,26 +15995,29 @@ newsgroup."
       (if (and (setq method (gnus-info-method info))
               (not (gnus-server-equal
                     gnus-select-method
-                    (setq fmethod (gnus-server-get-method nil method))))
+                    (setq method (gnus-server-get-method nil method))))
               (not (gnus-secondary-method-p method)))
          ;; These groups are foreign.  Check the level.
-         (if (<= (gnus-info-level info) foreign-level)
-             (setq active (gnus-activate-group (gnus-info-group info) 'scan)))
-
+         (when (<= (gnus-info-level info) foreign-level)
+           (setq active (gnus-activate-group group 'scan))
+           (unless (inline (gnus-virtual-group-p group))
+             (inline (gnus-close-group group)))
+           (when (fboundp (intern (concat (symbol-name (car method))
+                                          "-request-update-info")))
+             (inline (gnus-request-update-info info method))))
        ;; These groups are native or secondary.
-       (if (<= (gnus-info-level info) level)
-           (or gnus-read-active-file
-               (setq active (gnus-activate-group
-                             (gnus-info-group info) 'scan)))))
+       (when (and (<= (gnus-info-level info) level)
+                  (not gnus-read-active-file))
+         (setq active (gnus-activate-group group 'scan))
+         (inline (gnus-close-group group))))
 
+      ;; Get the number of unread articles in the group.
       (if active
-         (gnus-get-unread-articles-in-group info active t)
+         (inline (gnus-get-unread-articles-in-group info active))
        ;; The group couldn't be reached, so we nix out the number of
        ;; unread articles and stuff.
        (gnus-set-active group nil)
-       (setcar (gnus-gethash group gnus-newsrc-hashtb) t))
-
-      (setq newsrc (cdr newsrc)))
+       (setcar (gnus-gethash group gnus-newsrc-hashtb) t)))
 
     (gnus-message 5 "Checking new news...done")))
 
@@ -15069,14 +16030,14 @@ newsgroup."
     (setq gnus-newsrc-hashtb (gnus-make-hashtable (length alist)))
     (setq alist
          (setq prev (setq gnus-newsrc-alist
-                          (if (equal (car (car gnus-newsrc-alist))
+                          (if (equal (caar gnus-newsrc-alist)
                                      "dummy.group")
                               gnus-newsrc-alist
                             (cons (list "dummy.group" 0 nil) alist)))))
     (while alist
       (gnus-sethash
-       (car (car alist))
-       (cons (and ohashtb (car (gnus-gethash (car (car alist)) ohashtb)))
+       (caar alist)
+       (cons (and ohashtb (car (gnus-gethash (caar alist) ohashtb)))
             prev)
        gnus-newsrc-hashtb)
       (setq prev alist
@@ -15089,96 +16050,15 @@ newsgroup."
     (setq gnus-killed-hashtb
          (gnus-make-hashtable
           (+ (length gnus-killed-list) (length gnus-zombie-list))))
-    (while lists
-      (setq list (symbol-value (car lists)))
-      (setq lists (cdr lists))
+    (while (setq list (pop lists))
+      (setq list (symbol-value list))
       (while list
-       (gnus-sethash (car list) (car list) gnus-killed-hashtb)
-       (setq list (cdr list))))))
+       (gnus-sethash (car list) (pop list) gnus-killed-hashtb)))))
 
-(defun gnus-get-unread-articles-in-group (info active &optional update)
-  ;; Allow the backend to update the info in the group.
-  (when update
-    (gnus-request-update-info
-     info (gnus-find-method-for-group (gnus-info-group info))))
-  (let* ((range (gnus-info-read info))
-        (num 0)
-        (marked (gnus-info-marks info)))
-    ;; If a cache is present, we may have to alter the active info.
-    (and gnus-use-cache
-        (gnus-cache-possibly-alter-active (gnus-info-group info) active))
-    ;; Modify the list of read articles according to what articles
-    ;; are available; then tally the unread articles and add the
-    ;; number to the group hash table entry.
-    (cond
-     ((zerop (cdr active))
-      (setq num 0))
-     ((not range)
-      (setq num (- (1+ (cdr active)) (car active))))
-     ((not (listp (cdr range)))
-      ;; Fix a single (num . num) range according to the
-      ;; active hash table.
-      ;; Fix by Carsten Bormann <cabo@Informatik.Uni-Bremen.DE>.
-      (and (< (cdr range) (car active)) (setcdr range (1- (car active))))
-      (and (> (cdr range) (cdr active)) (setcdr range (cdr active)))
-      ;; Compute number of unread articles.
-      (setq num (max 0 (- (cdr active) (- (1+ (cdr range)) (car range))))))
-     (t
-      ;; The read list is a list of ranges.  Fix them according to
-      ;; the active hash table.
-      ;; First peel off any elements that are below the lower
-      ;; active limit.
-      (while (and (cdr range)
-                 (>= (car active)
-                     (or (and (atom (car (cdr range))) (car (cdr range)))
-                         (car (car (cdr range))))))
-       (if (numberp (car range))
-           (setcar range
-                   (cons (car range)
-                         (or (and (numberp (car (cdr range)))
-                                  (car (cdr range)))
-                             (cdr (car (cdr range))))))
-         (setcdr (car range)
-                 (or (and (numberp (nth 1 range)) (nth 1 range))
-                     (cdr (car (cdr range))))))
-       (setcdr range (cdr (cdr range))))
-      ;; Adjust the first element to be the same as the lower limit.
-      (if (and (not (atom (car range)))
-              (< (cdr (car range)) (car active)))
-         (setcdr (car range) (1- (car active))))
-      ;; Then we want to peel off any elements that are higher
-      ;; than the upper active limit.
-      (let ((srange range))
-       ;; Go past all legal elements.
-       (while (and (cdr srange)
-                   (<= (or (and (atom (car (cdr srange)))
-                                (car (cdr srange)))
-                           (car (car (cdr srange)))) (cdr active)))
-         (setq srange (cdr srange)))
-       (if (cdr srange)
-           ;; Nuke all remaining illegal elements.
-           (setcdr srange nil))
-
-       ;; Adjust the final element.
-       (if (and (not (atom (car srange)))
-                (> (cdr (car srange)) (cdr active)))
-           (setcdr (car srange) (cdr active))))
-      ;; Compute the number of unread articles.
-      (while range
-       (setq num (+ num (- (1+ (or (and (atom (car range)) (car range))
-                                   (cdr (car range))))
-                           (or (and (atom (car range)) (car range))
-                               (car (car range))))))
-       (setq range (cdr range)))
-      (setq num (max 0 (- (cdr active) num)))))
-    ;; Set the number of unread articles.
-    (setcar (gnus-gethash (gnus-info-group info) gnus-newsrc-hashtb) num)
-    num))
-
-(defun gnus-activate-group (group &optional scan)
+(defun gnus-activate-group (group &optional scan dont-check method)
   ;; Check whether a group has been activated or not.
   ;; If SCAN, request a scan of that group as well.
-  (let ((method (gnus-find-method-for-group group))
+  (let ((method (or method (gnus-find-method-for-group group)))
        active)
     (and (gnus-check-server method)
         ;; We escape all bugs and quit here to make it possible to
@@ -15190,7 +16070,7 @@ newsgroup."
                (gnus-request-scan group method))
           t)
         (condition-case ()
-            (gnus-request-group group)
+            (gnus-request-group group dont-check method)
        ;   (error nil)
           (quit nil))
         (save-excursion
@@ -15214,7 +16094,6 @@ Returns whether the updating was successful."
   (let* ((active (or gnus-newsgroup-active (gnus-active group)))
         (entry (gnus-gethash group gnus-newsrc-hashtb))
         (info (nth 2 entry))
-        (marked (gnus-info-marks info))
         (prev 1)
         (unread (sort (copy-sequence unread) '<))
         read)
@@ -15276,32 +16155,60 @@ Returns whether the updating was successful."
        (setq killed (cdr killed)))
       (setq lists (cdr lists)))))
 
+(defun gnus-get-killed-groups ()
+  "Go through the active hashtb and all all unknown groups as killed."
+  ;; First make sure active file has been read.
+  (unless (gnus-read-active-file-p)
+    (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))
+
 ;; Get the active file(s) from the backend(s).
 (defun gnus-read-active-file ()
   (gnus-group-set-mode-line)
-  (let ((methods (nconc (copy-sequence
-                        (if (gnus-check-server gnus-select-method)
-                            ;; The native server is available.
-                            (cons gnus-select-method 
-                                  gnus-secondary-select-methods)
-                          ;; The native server is down, so we just do the
-                          ;; secondary ones.
-                          gnus-secondary-select-methods))
-                       (list gnus-message-archive-method)))
+  (let ((methods 
+        (append
+         (if (gnus-check-server gnus-select-method)
+             ;; The native server is available.
+             (cons gnus-select-method gnus-secondary-select-methods)
+           ;; The native server is down, so we just do the
+           ;; secondary ones.
+           gnus-secondary-select-methods)
+         ;; Also read from the archive server.
+         (when gnus-message-archive-method
+           (list "archive"))))
        list-type)
     (setq gnus-have-read-active-file nil)
     (save-excursion
       (set-buffer nntp-server-buffer)
       (while methods
-       (let* ((method (gnus-server-get-method nil (car methods)))
+       (let* ((method (if (stringp (car methods))
+                          (gnus-server-get-method nil (car methods))
+                        (car methods)))
               (where (nth 1 method))
               (mesg (format "Reading active file%s via %s..."
                             (if (and where (not (zerop (length where))))
                                 (concat " from " where) "")
                             (car method))))
          (gnus-message 5 mesg)
-         (if (not (gnus-check-server method))
-             ()
+         (when (gnus-check-server method)
            ;; Request that the backend scan its incoming messages.
            (and (gnus-check-backend-function 'request-scan (car method))
                 (gnus-request-scan nil method))
@@ -15310,39 +16217,35 @@ Returns whether the updating was successful."
                   (gnus-check-backend-function 'retrieve-groups (car method)))
              (let ((newsrc (cdr gnus-newsrc-alist))
                    (gmethod (gnus-server-get-method nil method))
-                   groups)
-               (while newsrc
-                 (and (gnus-server-equal
-                       (gnus-find-method-for-group
-                        (car (car newsrc)) (car newsrc))
-                       gmethod)
-                      (setq groups (cons (gnus-group-real-name
-                                          (car (car newsrc))) groups)))
-                 (setq newsrc (cdr newsrc)))
-               (gnus-check-server method)
-               (setq list-type (gnus-retrieve-groups groups method))
-               (cond
-                ((not list-type)
-                 (gnus-message
-                  1 "Cannot read partial active file from %s server."
-                  (car method))
-                 (ding)
-                 (sit-for 2))
-                ((eq list-type 'active)
-                 (gnus-active-to-gnus-format method gnus-active-hashtb))
-                (t
-                 (gnus-groups-to-gnus-format method gnus-active-hashtb)))))
+                   groups info)
+               (while (setq info (pop newsrc))
+                 (when (gnus-server-equal
+                        (gnus-find-method-for-group 
+                         (gnus-info-group info) info)
+                        gmethod)
+                   (push (gnus-group-real-name (gnus-info-group info)) 
+                         groups)))
+               (when groups
+                 (gnus-check-server method)
+                 (setq list-type (gnus-retrieve-groups groups method))
+                 (cond
+                  ((not list-type)
+                   (gnus-error
+                    1.2 "Cannot read partial active file from %s server."
+                    (car method)))
+                  ((eq list-type 'active)
+                   (gnus-active-to-gnus-format method gnus-active-hashtb))
+                  (t
+                   (gnus-groups-to-gnus-format method gnus-active-hashtb))))))
             (t
              (if (not (gnus-request-list method))
-                 (progn
-                   (unless (equal method gnus-message-archive-method)
-                     (gnus-message 1 "Cannot read active file from %s server."
-                                   (car method))
-                     (ding)))
-               (gnus-active-to-gnus-format method)
+                 (unless (equal method gnus-message-archive-method)
+                   (gnus-error 1 "Cannot read active file from %s server."
+                               (car method)))
+               (gnus-message 5 mesg)
+               (gnus-active-to-gnus-format method gnus-active-hashtb)
                ;; We mark this active file as read.
-               (setq gnus-have-read-active-file
-                     (cons method gnus-have-read-active-file))
+               (push method gnus-have-read-active-file)
                (gnus-message 5 "%sdone" mesg))))))
        (setq methods (cdr methods))))))
 
@@ -15359,8 +16262,7 @@ Returns whether the updating was successful."
                            (if (equal method gnus-select-method)
                                (gnus-make-hashtable
                                 (count-lines (point-min) (point-max)))
-                             (gnus-make-hashtable 4096))))))
-       (flag-hashtb (gnus-make-hashtable 60)))
+                             (gnus-make-hashtable 4096)))))))
     ;; Delete unnecessary lines.
     (goto-char (point-min))
     (while (search-forward "\nto." nil t)
@@ -15515,11 +16417,12 @@ If FORCE is non-nil, the .newsrc file is read."
       ;; file (ticked articles, killed groups, foreign methods, etc.)
       (gnus-read-newsrc-el-file quick-file)
 
-      (if (or force
-             (and (file-newer-than-file-p newsrc-file quick-file)
-                  (file-newer-than-file-p newsrc-file
-                                          (concat quick-file "d")))
-             (not gnus-newsrc-alist))
+      (if (and (file-exists-p gnus-current-startup-file)
+              (or force
+                  (and (file-newer-than-file-p newsrc-file quick-file)
+                       (file-newer-than-file-p newsrc-file
+                                               (concat quick-file "d")))
+                  (not gnus-newsrc-alist)))
          ;; We read the .newsrc file.  Note that if there if a
          ;; .newsrc.eld file exists, it has already been read, and
          ;; the `gnus-newsrc-hashtb' has been created.  While reading
@@ -15536,8 +16439,60 @@ If FORCE is non-nil, the .newsrc file is read."
            (gnus-message 5 "Reading %s...done" newsrc-file)))
 
       ;; Read any slave files.
-      (or gnus-slave
-         (gnus-master-read-slave-newsrc)))))
+      (unless gnus-slave
+       (gnus-master-read-slave-newsrc))
+      
+      ;; Convert old to new.
+      (gnus-convert-old-newsrc))))
+
+(defun gnus-continuum-version (version)
+  "Return VERSION as a floating point number."
+  (when (or (string-match "^\\([^ ]+\\)? ?Gnus v?\\([0-9.]+\\)$" version)
+           (string-match "^\\(.?\\)gnus-\\([0-9.]+\\)$" version))
+    (let* ((alpha (and (match-beginning 1) (match-string 1 version)))
+          (number (match-string 2 version))
+          major minor least)
+      (string-match "\\([0-9]\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?" number)
+      (setq major (string-to-number (match-string 1 number)))
+      (setq minor (string-to-number (match-string 2 number)))
+      (setq least (if (match-beginning 3)
+                     (string-to-number (match-string 3 number))
+                   0))
+      (string-to-number
+       (if (zerop major)
+          (format "%s00%02d%02d"
+                  (cond 
+                   ((member alpha '("(ding)" "d")) "4.99")
+                   ((member alpha '("September" "s")) "5.01")
+                   ((member alpha '("Red" "r")) "5.03"))
+                  minor least)
+        (format "%d.%02d%02d" major minor least))))))
+
+(defun gnus-convert-old-newsrc ()
+  "Convert old newsrc into the new format, if needed."
+  (let ((fcv (and gnus-newsrc-file-version
+                 (gnus-continuum-version gnus-newsrc-file-version))))
+    (cond
+     ;; No .newsrc.eld file was loaded.
+     ((null fcv) nil)
+     ;; Gnus 5 .newsrc.eld was loaded.
+     ((< fcv (gnus-continuum-version "September Gnus v0.1"))
+      (gnus-convert-old-ticks)))))
+
+(defun gnus-convert-old-ticks ()
+  (let ((newsrc (cdr gnus-newsrc-alist))
+       marks info dormant ticked)
+    (while (setq info (pop newsrc))
+      (when (setq marks (gnus-info-marks info))
+       (setq dormant (cdr (assq 'dormant marks))
+             ticked (cdr (assq 'tick marks)))
+       (when (or dormant ticked)
+         (gnus-info-set-read
+          info
+          (gnus-add-to-range
+           (gnus-info-read info)
+           (nconc (gnus-uncompress-range dormant)
+                  (gnus-uncompress-range ticked)))))))))
 
 (defun gnus-read-newsrc-el-file (file)
   (let ((ding-file (concat file "d")))
@@ -15547,8 +16502,7 @@ If FORCE is non-nil, the .newsrc file is read."
       (condition-case nil
          (load ding-file t t t)
        (error
-        (gnus-message 1 "Error in %s" ding-file)
-        (ding)))
+        (gnus-error 1 "Error in %s" ding-file)))
       (when gnus-newsrc-assoc
        (setq gnus-newsrc-alist gnus-newsrc-assoc)))
     (gnus-make-hashtable-from-newsrc-alist)
@@ -15561,7 +16515,7 @@ If FORCE is non-nil, the .newsrc file is read."
 
 ;; Parse the old-style quick startup file
 (defun gnus-read-old-newsrc-el-file (file)
-  (let (newsrc killed marked group m)
+  (let (newsrc killed marked group m info)
     (prog1
        (let ((gnus-killed-assoc nil)
              gnus-marked-assoc gnus-newsrc-alist gnus-newsrc-assoc)
@@ -15573,33 +16527,30 @@ If FORCE is non-nil, the .newsrc file is read."
                  killed gnus-killed-assoc
                  marked gnus-marked-assoc)))
       (setq gnus-newsrc-alist nil)
-      (while newsrc
-       (setq group (car newsrc))
-       (let ((info (gnus-get-info (car group))))
-         (if info
-             (progn
-               (gnus-info-set-read info (cdr (cdr group)))
-               (gnus-info-set-level
-                info (if (nth 1 group) gnus-level-default-subscribed
-                       gnus-level-default-unsubscribed))
-               (setq gnus-newsrc-alist (cons info gnus-newsrc-alist)))
-           (setq gnus-newsrc-alist
-                 (cons
-                  (setq info
-                        (list (car group)
-                              (if (nth 1 group) gnus-level-default-subscribed
-                                gnus-level-default-unsubscribed)
-                              (cdr (cdr group))))
-                  gnus-newsrc-alist)))
-         (if (setq m (assoc (car group) marked))
-             (gnus-info-set-marks
-              info (cons (list (cons 'tick (gnus-compress-sequence
-                                            (sort (cdr m) '<) t)))
-                         nil))))
-       (setq newsrc (cdr newsrc)))
+      (while (setq group (pop newsrc))
+       (if (setq info (gnus-get-info (car group)))
+           (progn
+             (gnus-info-set-read info (cddr group))
+             (gnus-info-set-level
+              info (if (nth 1 group) gnus-level-default-subscribed
+                     gnus-level-default-unsubscribed))
+             (setq gnus-newsrc-alist (cons info gnus-newsrc-alist)))
+         (push (setq info
+                     (list (car group)
+                           (if (nth 1 group) gnus-level-default-subscribed
+                             gnus-level-default-unsubscribed)
+                           (cddr group)))
+               gnus-newsrc-alist))
+       ;; Copy marks into info.
+       (when (setq m (assoc (car group) marked))
+         (unless (nthcdr 3 info)
+           (nconc info (list nil)))
+         (gnus-info-set-marks
+          info (list (cons 'tick (gnus-compress-sequence 
+                                  (sort (cdr m) '<) t))))))
       (setq newsrc killed)
       (while newsrc
-       (setcar newsrc (car (car newsrc)))
+       (setcar newsrc (caar newsrc))
        (setq newsrc (cdr newsrc)))
       (setq gnus-killed-list killed))
     ;; The .el file version of this variable does not begin with
@@ -15740,11 +16691,9 @@ If FORCE is non-nil, the .newsrc file is read."
                  (progn
                    ;; The line was buggy.
                    (setq group nil)
-                   (gnus-message 3 "Mangled line: %s"
-                                 (buffer-substring (gnus-point-at-bol)
-                                                   (gnus-point-at-eol)))
-                   (ding)
-                   (sit-for 1)))
+                   (gnus-error 3.1 "Mangled line: %s"
+                               (buffer-substring (gnus-point-at-bol)
+                                                 (gnus-point-at-eol)))))
              nil))
          ;; Skip past ", ".  Spaces are illegal in these ranges, but
          ;; we allow them, because it's a common mistake to put a
@@ -15798,8 +16747,8 @@ If FORCE is non-nil, the .newsrc file is read."
            entry mentry)
        (while rc
          (or (null (nth 4 (car rc)))   ; It's a native group.
-             (assoc (car (car rc)) newsrc) ; It's already in the alist.
-             (if (setq entry (assoc (car (car prev)) newsrc))
+             (assoc (caar rc) newsrc) ; It's already in the alist.
+             (if (setq entry (assoc (caar prev) newsrc))
                  (setcdr (setq mentry (memq entry newsrc))
                          (cons (car rc) (cdr mentry)))
                (setq newsrc (cons (car rc) newsrc))))
@@ -15902,6 +16851,7 @@ If FORCE is non-nil, the .newsrc file is read."
          (setq version-control 'never)
          (setq buffer-file-name
                (concat gnus-current-startup-file ".eld"))
+         (setq default-directory (file-name-directory buffer-file-name))
          (gnus-add-current-to-buffer-list)
          (buffer-disable-undo (current-buffer))
          (erase-buffer)
@@ -15912,7 +16862,8 @@ If FORCE is non-nil, the .newsrc file is read."
          (kill-buffer (current-buffer))
          (gnus-message
           5 "Saving %s.eld...done" gnus-current-startup-file))
-       (gnus-dribble-delete-file)))))
+       (gnus-dribble-delete-file)
+       (gnus-group-set-mode-line)))))
 
 (defun gnus-gnus-to-quick-newsrc-format ()
   "Insert Gnus variables such as gnus-newsrc-alist in lisp format."
@@ -15933,49 +16884,48 @@ If FORCE is non-nil, the .newsrc file is read."
     (while variables
       (when (and (boundp (setq variable (pop variables)))
                 (symbol-value variable))
-       (insert "(setq " (symbol-name variable) " '"
-               (prin1-to-string (symbol-value variable)) ")\n")))))
+       (insert "(setq " (symbol-name variable) " '")
+       (prin1 (symbol-value variable) (current-buffer))
+       (insert ")\n")))))
 
 (defun gnus-gnus-to-newsrc-format ()
   ;; Generate and save the .newsrc file.
-  (let ((newsrc (cdr gnus-newsrc-alist))
-       info ranges range)
-    (save-excursion
-      (set-buffer (create-file-buffer gnus-current-startup-file))
+  (save-excursion
+    (set-buffer (create-file-buffer gnus-current-startup-file))
+    (let ((newsrc (cdr gnus-newsrc-alist))
+         (standard-output (current-buffer))
+         info ranges range method)
       (setq buffer-file-name gnus-current-startup-file)
+      (setq default-directory (file-name-directory buffer-file-name))
       (buffer-disable-undo (current-buffer))
       (erase-buffer)
       ;; Write options.
       (if gnus-newsrc-options (insert gnus-newsrc-options))
       ;; Write subscribed and unsubscribed.
-      (while newsrc
-       (setq info (car newsrc))
-       (if (not (gnus-info-method info))
-           ;; Don't write foreign groups to .newsrc.
-           (progn
-             (insert (gnus-info-group info)
-                     (if (> (gnus-info-level info) gnus-level-subscribed)
-                         "!" ":"))
-             (if (setq ranges (gnus-info-read info))
-                 (progn
-                   (insert " ")
-                   (if (not (listp (cdr ranges)))
-                       (if (= (car ranges) (cdr ranges))
-                           (insert (int-to-string (car ranges)))
-                         (insert (int-to-string (car ranges)) "-"
-                                 (int-to-string (cdr ranges))))
-                     (while ranges
-                       (setq range (car ranges)
-                             ranges (cdr ranges))
-                       (if (or (atom range) (= (car range) (cdr range)))
-                           (insert (int-to-string
-                                    (or (and (atom range) range)
-                                        (car range))))
-                         (insert (int-to-string (car range)) "-"
-                                 (int-to-string (cdr range))))
-                       (if ranges (insert ","))))))
-             (insert "\n")))
-       (setq newsrc (cdr newsrc)))
+      (while (setq info (pop newsrc))
+       ;; Don't write foreign groups to .newsrc.
+       (when (or (null (setq method (gnus-info-method info)))
+                 (equal method "native")
+                 (gnus-server-equal method gnus-select-method))
+         (insert (gnus-info-group info)
+                 (if (> (gnus-info-level info) gnus-level-subscribed)
+                     "!" ":"))
+         (when (setq ranges (gnus-info-read info))
+           (insert " ")
+           (if (not (listp (cdr ranges)))
+               (if (= (car ranges) (cdr ranges))
+                   (princ (car ranges))
+                 (princ (car ranges))
+                 (insert "-")
+                 (princ (cdr ranges)))
+             (while (setq range (pop ranges))
+               (if (or (atom range) (= (car range) (cdr range)))
+                   (princ (or (and (atom range) range) (car range)))
+                 (princ (car range))
+                 (insert "-")
+                 (princ (cdr range)))
+               (if ranges (insert ",")))))
+         (insert "\n")))
       (make-local-variable 'version-control)
       (setq version-control 'never)
       ;; It has been reported that sometime the modtime on the .newsrc
@@ -15992,8 +16942,10 @@ If FORCE is non-nil, the .newsrc file is read."
       (save-buffer)
       (kill-buffer (current-buffer)))))
 
-
+\f
+;;;
 ;;; Slave functions.
+;;;
 
 (defun gnus-slave-save-newsrc ()
   (save-excursion
@@ -16024,7 +16976,7 @@ If FORCE is non-nil, the .newsrc file is read."
                              (list (nth 5 (file-attributes file)) file))
                            slave-files)
                    (lambda (f1 f2)
-                     (or (< (car (car f1)) (car (car f2)))
+                     (or (< (caar f1) (caar f2))
                          (< (nth 1 (car f1)) (nth 1 (car f2)))))))
        (while slave-files
          (erase-buffer)
@@ -16035,9 +16987,7 @@ If FORCE is non-nil, the .newsrc file is read."
                    (eval-buffer (current-buffer))
                    t)
                (error
-                (gnus-message 3 "Possible error in %s" file)
-                (ding)
-                (sit-for 2)
+                (gnus-error 3.2 "Possible error in %s" file)
                 nil))
              (or gnus-slave ; Slaves shouldn't delete these files.
                  (condition-case ()
@@ -16046,20 +16996,27 @@ If FORCE is non-nil, the .newsrc file is read."
          (setq slave-files (cdr slave-files))))
       (gnus-message 7 "Reading slave newsrcs...done"))))
 
-
+\f
+;;;
 ;;; Group description.
+;;;
 
 (defun gnus-read-all-descriptions-files ()
   (let ((methods (cons gnus-select-method 
-                      (cons gnus-message-archive-method
-                            gnus-secondary-select-methods))))
+                      (nconc
+                       (when gnus-message-archive-method
+                         (list "archive"))
+                       gnus-secondary-select-methods))))
     (while methods
       (gnus-read-descriptions-file (car methods))
       (setq methods (cdr methods)))
     t))
 
 (defun gnus-read-descriptions-file (&optional method)
-  (let ((method (or method gnus-select-method)))
+  (let ((method (or method gnus-select-method))
+       group)
+    (when (stringp method)
+      (setq method (gnus-server-to-method method)))
     ;; We create the hashtable whether we manage to read the desc file
     ;; to avoid trying to re-read after a failed read.
     (or gnus-description-hashtb
@@ -16078,35 +17035,43 @@ If FORCE is non-nil, the .newsrc file is read."
       (gnus-message 1 "Couldn't read newsgroups descriptions")
       nil)
      (t
-      (let (group)
-       (save-excursion
-         (save-restriction
-           (set-buffer nntp-server-buffer)
-           (goto-char (point-min))
-           (if (or (search-forward "\n.\n" nil t)
+      (save-excursion
+       (save-restriction
+         (set-buffer nntp-server-buffer)
+         (goto-char (point-min))
+         (when (or (search-forward "\n.\n" nil t)
                    (goto-char (point-max)))
-               (progn
-                 (beginning-of-line)
-                 (narrow-to-region (point-min) (point))))
-           (goto-char (point-min))
-           (while (not (eobp))
-             ;; If we get an error, we set group to 0, which is not a
-             ;; symbol...
-             (setq group
-                   (condition-case ()
-                       (let ((obarray gnus-description-hashtb))
-                         ;; Group is set to a symbol interned in this
-                         ;; hash table.
-                         (read nntp-server-buffer))
-                     (error 0)))
-             (skip-chars-forward " \t")
-             ;; ...  which leads to this line being effectively ignored.
-             (and (symbolp group)
-                  (set group (buffer-substring
-                              (point) (progn (end-of-line) (point)))))
-             (forward-line 1))))
-       (gnus-message 5 "Reading descriptions file...done")
-       t)))))
+           (beginning-of-line)
+           (narrow-to-region (point-min) (point)))
+         ;; If these are groups from a foreign select method, we insert the
+         ;; group prefix in front of the group names.
+         (and method (not (gnus-server-equal
+                           (gnus-server-get-method nil method)
+                           (gnus-server-get-method nil gnus-select-method)))
+              (let ((prefix (gnus-group-prefixed-name "" method)))
+                (goto-char (point-min))
+                (while (and (not (eobp))
+                            (progn (insert prefix)
+                                   (zerop (forward-line 1)))))))
+         (goto-char (point-min))
+         (while (not (eobp))
+           ;; If we get an error, we set group to 0, which is not a
+           ;; symbol...
+           (setq group
+                 (condition-case ()
+                     (let ((obarray gnus-description-hashtb))
+                       ;; Group is set to a symbol interned in this
+                       ;; hash table.
+                       (read nntp-server-buffer))
+                   (error 0)))
+           (skip-chars-forward " \t")
+           ;; ...  which leads to this line being effectively ignored.
+           (and (symbolp group)
+                (set group (buffer-substring
+                            (point) (progn (end-of-line) (point)))))
+           (forward-line 1))))
+      (gnus-message 5 "Reading descriptions file...done")
+      t))))
 
 (defun gnus-group-get-description (group)
   "Get the description of a group by sending XGTITLE to the server."
@@ -16117,6 +17082,7 @@ If FORCE is non-nil, the .newsrc file is read."
       (when (looking-at "[^ \t]+[ \t]+\\(.*\\)")
        (match-string 1)))))
 
+\f
 ;;;
 ;;; Buffering of read articles.
 ;;;
@@ -16140,6 +17106,8 @@ If FORCE is non-nil, the .newsrc file is read."
   (unless gnus-backlog-hashtb
     (setq gnus-backlog-hashtb (make-vector 1023 0))))
 
+(gnus-add-shutdown 'gnus-backlog-shutdown 'gnus)
+
 (defun gnus-backlog-shutdown ()
   "Clear all backlog variables and buffers."
   (when (get-buffer gnus-backlog-buffer)
@@ -16168,7 +17136,7 @@ If FORCE is non-nil, the .newsrc file is read."
          (setq b (point))
          (insert-buffer-substring buffer)
          ;; Tag the beginning of the article with the ident.
-         (put-text-property b (1+ b) 'gnus-backlog ident))))))
+         (gnus-put-text-property b (1+ b) 'gnus-backlog ident))))))
 
 (defun gnus-backlog-remove-oldest-article ()
   (save-excursion
@@ -16186,30 +17154,53 @@ If FORCE is non-nil, the .newsrc file is read."
         (point) (next-single-property-change
                  (1+ (point)) 'gnus-backlog nil (point-max)))))))
 
+(defun gnus-backlog-remove-article (group number)
+  "Remove article NUMBER in GROUP from the backlog."
+  (when (numberp number)
+    (gnus-backlog-setup)
+    (let ((ident (intern (concat group ":" (int-to-string number))
+                        gnus-backlog-hashtb))
+         beg end)
+      (when (memq ident gnus-backlog-articles)
+       ;; It was in the backlog.
+       (save-excursion
+         (set-buffer (gnus-backlog-buffer))
+         (let (buffer-read-only)
+           (when (setq beg (text-property-any
+                            (point-min) (point-max) 'gnus-backlog
+                            ident))
+             ;; Find the end (i. e., the beginning of the next article).
+             (setq end
+                   (next-single-property-change
+                    (1+ beg) 'gnus-backlog (current-buffer) (point-max)))
+             (delete-region beg end)
+             ;; Return success.
+             t)))))))
+
 (defun gnus-backlog-request-article (group number buffer)
-  (gnus-backlog-setup)
-  (let ((ident (intern (concat group ":" (int-to-string number))
-                      gnus-backlog-hashtb))
-       beg end)
-    (when (memq ident gnus-backlog-articles)
-      ;; It was in the backlog.
-      (save-excursion
-       (set-buffer (gnus-backlog-buffer))
-       (if (not (setq beg (text-property-any
-                           (point-min) (point-max) 'gnus-backlog
-                           ident)))
-           ;; It wasn't in the backlog after all.
-           (progn
-             (setq gnus-backlog-articles (delq ident gnus-backlog-articles))
-             nil)
-         ;; Find the end (i. e., the beginning of the next article).
-         (setq end
-               (next-single-property-change
-                (1+ beg) 'gnus-backlog (current-buffer) (point-max)))))
-      (let ((buffer-read-only nil))
-       (erase-buffer)
-       (insert-buffer-substring gnus-backlog-buffer beg end)
-       t))))
+  (when (numberp number)
+    (gnus-backlog-setup)
+    (let ((ident (intern (concat group ":" (int-to-string number))
+                        gnus-backlog-hashtb))
+         beg end)
+      (when (memq ident gnus-backlog-articles)
+       ;; It was in the backlog.
+       (save-excursion
+         (set-buffer (gnus-backlog-buffer))
+         (if (not (setq beg (text-property-any
+                             (point-min) (point-max) 'gnus-backlog
+                             ident)))
+             ;; It wasn't in the backlog after all.
+             (ignore
+              (setq gnus-backlog-articles (delq ident gnus-backlog-articles)))
+           ;; Find the end (i. e., the beginning of the next article).
+           (setq end
+                 (next-single-property-change
+                  (1+ beg) 'gnus-backlog (current-buffer) (point-max)))))
+       (let ((buffer-read-only nil))
+         (erase-buffer)
+         (insert-buffer-substring gnus-backlog-buffer beg end)
+         t)))))
 
 ;; Allow redefinition of Gnus functions.