Synch with Emacs trunk.
[gnus] / lisp / gnus-start.el
index c5ca5bf..ff51530 100644 (file)
@@ -1,26 +1,25 @@
 ;;; gnus-start.el --- startup functions for Gnus
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
-;;        Free Software Foundation, Inc.
+
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+;;   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 (require 'gnus-spec)
 (require 'gnus-range)
 (require 'gnus-util)
-(require 'message)
-(eval-when-compile (require 'cl))
+(autoload 'message-make-date "message")
+(autoload 'gnus-agent-read-servers-validate "gnus-agent")
+(autoload 'gnus-agent-save-local "gnus-agent")
+(autoload 'gnus-agent-possibly-alter-active "gnus-agent")
+
+(eval-when-compile
+  (require 'cl))
+
+(defvar gnus-agent-covered-methods)
+(defvar gnus-agent-file-loading-local)
+(defvar gnus-agent-file-loading-cache)
 
 (defcustom gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc")
   "Your `.newsrc' file.
   :group 'gnus-start
   :type 'file)
 
+(defcustom gnus-backup-startup-file 'never
+  "Control use of version numbers for backups of `gnus-startup-file'.
+This variable takes the same values as the `version-control'
+variable."
+  :version "22.1"
+  :group 'gnus-start
+  :type '(choice (const :tag "Never" never)
+                (const :tag "If existing" nil)
+                (other :tag "Always" t)))
+
+(defcustom gnus-save-startup-file-via-temp-buffer t
+  "Whether to write the startup file contents to a buffer then save
+the buffer or write directly to the file.  The buffer is faster
+because all of the contents are written at once.  The direct write
+uses considerably less memory."
+  :version "22.1"
+  :group 'gnus-start
+  :type '(choice (const :tag "Write via buffer" t)
+                 (const :tag "Write directly to file" nil)))
+
 (defcustom gnus-init-file (nnheader-concat gnus-home-directory ".gnus")
   "Your Gnus Emacs-Lisp startup file name.
 If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
@@ -148,8 +176,13 @@ properly with all servers."
 
 (defconst gnus-level-unsubscribed 7
   "Groups with levels less than or equal to this variable are unsubscribed.
-Groups with levels less than `gnus-level-subscribed', which should be
-less than this variable, are subscribed.")
+
+Groups with levels less than `gnus-level-subscribed', which
+should be less than this variable, are subscribed.  Groups with
+levels from `gnus-level-subscribed' (exclusive) upto this
+variable (inclusive) are unsubscribed.  See also
+`gnus-level-zombie', `gnus-level-killed' and the Info node `Group
+Levels' for details.")
 
 (defconst gnus-level-zombie 8
   "Groups with this level are zombie groups.")
@@ -224,12 +257,17 @@ nil if you set this variable to nil.
 This variable can also be a regexp.  In that case, all groups that do
 not match this regexp will be removed before saving the list."
   :group 'gnus-newsrc
-  :type 'boolean)
+  :type '(radio (sexp :format "Non-nil\n"
+                     :match (lambda (widget value)
+                              (and value (not (stringp value))))
+                     :value t)
+               (const nil)
+               regexp))
 
 (defcustom gnus-ignored-newsgroups
   (mapconcat 'identity
             '("^to\\."                 ; not "real" groups
-              "^[0-9. \t]+ "           ; all digits in name
+              "^[0-9. \t]+\\( \\|$\\)" ; all digits in name
               "^[\"][]\"[#'()]"        ; bogus characters
               )
             "\\|")
@@ -263,8 +301,9 @@ claim them."
                (repeat function)))
 
 (defcustom gnus-subscribe-newsgroup-hooks nil
-  "*Hooks run after you subscribe to a new group. The hooks will be called
-with new group's name as argument."
+  "*Hooks run after you subscribe to a new group.
+The hooks will be called with new group's name as argument."
+  :version "22.1"
   :group 'gnus-group-new
   :type 'hook)
 
@@ -277,8 +316,8 @@ If, for instance, you want to subscribe to all newsgroups in the
 
 options -n no.all alt.all
 
-Gnus will the subscribe all new newsgroups in these hierarchies with
-the subscription method in this variable."
+Gnus will then subscribe all new newsgroups in these hierarchies
+with the subscription method in this variable."
   :group 'gnus-group-new
   :type '(radio (function-item gnus-subscribe-randomly)
                (function-item gnus-subscribe-alphabetically)
@@ -303,7 +342,7 @@ hierarchy in its entirety."
   :type 'boolean)
 
 (defcustom gnus-auto-subscribed-groups
-  "nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
+  "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl\\|^nnmaildir"
   "*All new groups that match this regexp will be subscribed automatically.
 Note that this variable only deals with new groups.  It has no effect
 whatsoever on old groups.
@@ -316,7 +355,7 @@ be subscribed using `gnus-subscribe-options-newsgroup-method'."
 
 (defcustom gnus-options-subscribe nil
   "*All new groups matching this regexp will be subscribed unconditionally.
-Note that this variable deals only with new newsgroups.         This variable
+Note that this variable deals only with new newsgroups.  This variable
 does not affect old newsgroups.
 
 New groups that match this regexp will not be handled by
@@ -328,7 +367,7 @@ be subscribed using `gnus-subscribe-options-newsgroup-method'."
 
 (defcustom gnus-options-not-subscribe nil
   "*All new groups matching this regexp will be ignored.
-Note that this variable deals only with new newsgroups.         This variable
+Note that this variable deals only with new newsgroups.  This variable
 does not affect old (already subscribed) newsgroups."
   :group 'gnus-group-new
   :type '(choice regexp
@@ -353,7 +392,7 @@ This hook is called after Gnus is connected to the NNTP server."
   :type 'hook)
 
 (defcustom gnus-before-startup-hook nil
-  "A hook called at before startup.
+  "A hook called before startup.
 This hook is called as the first thing when Gnus is started."
   :group 'gnus-start
   :type 'hook)
@@ -363,22 +402,35 @@ This hook is called as the first thing when Gnus is started."
   :group 'gnus-start
   :type 'hook)
 
-(defcustom gnus-setup-news-hook nil
+(defcustom gnus-setup-news-hook
+  '(gnus-fixup-nnimap-unread-after-getting-new-news)
   "A hook after reading the .newsrc file, but before generating the buffer."
   :group 'gnus-start
   :type 'hook)
 
+(defcustom gnus-get-top-new-news-hook nil
+  "A hook run just before Gnus checks for new news globally."
+  :version "22.1"
+  :group 'gnus-group-new
+  :type 'hook)
+
 (defcustom gnus-get-new-news-hook nil
   "A hook run just before Gnus checks for new news."
   :group 'gnus-group-new
   :type 'hook)
 
 (defcustom gnus-after-getting-new-news-hook
-  '(gnus-display-time-event-handler)
+  '(gnus-display-time-event-handler
+    gnus-fixup-nnimap-unread-after-getting-new-news)
   "*A hook run after Gnus checks for new news when Gnus is already running."
   :group 'gnus-group-new
   :type 'hook)
 
+(defcustom gnus-read-newsrc-el-hook nil
+  "A hook called after reading the newsrc.eld? file."
+  :group 'gnus-newsrc
+  :type 'hook)
+
 (defcustom gnus-save-newsrc-hook nil
   "A hook called before saving any of the newsrc files."
   :group 'gnus-newsrc
@@ -396,16 +448,24 @@ Can be used to turn version control on or off."
   :group 'gnus-newsrc
   :type 'hook)
 
+(defcustom gnus-group-mode-hook nil
+  "Hook for Gnus group mode."
+  :group 'gnus-group-various
+  :options '(gnus-topic-mode)
+  :type 'hook)
+
 (defcustom gnus-always-read-dribble-file nil
   "Unconditionally read the dribble file."
   :group 'gnus-newsrc
   :type 'boolean)
 
-(defvar gnus-startup-file-coding-system 'binary
-  "*Coding system for startup file.")
-
 ;;; Internal variables
 
+;; Fixme: deal with old emacs-mule when mm-universal-coding-system is
+;; utf-8-emacs.
+(defvar gnus-ding-file-coding-system mm-universal-coding-system
+  "Coding system for ding file.")
+
 (defvar gnus-newsrc-file-version nil)
 (defvar gnus-override-subscribe-method nil)
 (defvar gnus-dribble-buffer nil)
@@ -432,39 +492,37 @@ Can be used to turn version control on or off."
     (if gnus-init-inhibit
        (setq gnus-init-inhibit nil)
       (setq gnus-init-inhibit inhibit-next)
-      (let ((files (list gnus-site-init-file gnus-init-file))
-           file)
-       (while files
-         (and (setq file (pop files))
-              (or (and (file-exists-p file)
-                       ;; Don't try to load a directory.
-                       (not (file-directory-p file)))
-                  (file-exists-p (concat file ".el"))
-                  (file-exists-p (concat file ".elc")))
-              (condition-case var
-                  (let ((coding-system-for-read
-                         gnus-startup-file-coding-system))
-                    (load file nil t))
-                (error
-                 (error "Error in %s: %s" file var)))))))))
+      (dolist (file (list gnus-site-init-file gnus-init-file))
+       (when (and file
+                  (locate-library file))
+         (if (or debug-on-error debug-on-quit)
+             (load file nil t)
+           (condition-case var
+               (load file nil t)
+             (error
+              (error "Error in %s: %s" file (cadr var))))))))))
 
 ;; For subscribing new newsgroup
 
 (defun gnus-subscribe-hierarchical-interactive (groups)
   (let ((groups (sort groups 'string<))
-       prefixes prefix start ans group starts)
+       prefixes prefix start ans group starts real-group)
     (while groups
       (setq prefixes (list "^"))
       (while (and groups prefixes)
-       (while (not (string-match (car prefixes) (car groups)))
+       (while (not (string-match (car prefixes)
+                                 (gnus-group-real-name (car groups))))
          (setq prefixes (cdr prefixes)))
        (setq prefix (car prefixes))
        (setq start (1- (length prefix)))
-       (if (and (string-match "[^\\.]\\." (car groups) start)
+       (if (and (string-match "[^\\.]\\." (gnus-group-real-name (car groups))
+                              start)
                 (cdr groups)
                 (setq prefix
-                      (concat "^" (substring (car groups) 0 (match-end 0))))
-                (string-match prefix (cadr groups)))
+                      (concat "^" (substring
+                                   (gnus-group-real-name (car groups))
+                                   0 (match-end 0))))
+                (string-match prefix (gnus-group-real-name (cadr groups))))
            (progn
              (push prefix prefixes)
              (message "Descend hierarchy %s? ([y]nsq): "
@@ -476,16 +534,18 @@ Can be used to turn version control on or off."
                         (substring prefix 1 (1- (length prefix)))))
              (cond ((= ans ?n)
                     (while (and groups
-                                (string-match prefix
-                                              (setq group (car groups))))
+                                (setq group (car groups)
+                                      real-group (gnus-group-real-name group))
+                                (string-match prefix real-group))
                       (push group gnus-killed-list)
                       (gnus-sethash group group gnus-killed-hashtb)
                       (setq groups (cdr groups)))
                     (setq starts (cdr starts)))
                    ((= ans ?s)
                     (while (and groups
-                                (string-match prefix
-                                              (setq group (car groups))))
+                                (setq group (car groups)
+                                      real-group (gnus-group-real-name group))
+                                (string-match prefix real-group))
                       (gnus-sethash group group gnus-killed-hashtb)
                       (gnus-subscribe-alphabetically (car groups))
                       (setq groups (cdr groups)))
@@ -522,7 +582,7 @@ Can be used to turn version control on or off."
   (gnus-subscribe-newsgroup newsgroup))
 
 (defun gnus-subscribe-alphabetically (newgroup)
-  "Subscribe new NEWSGROUP and insert it in alphabetical order."
+  "Subscribe new NEWGROUP and insert it in alphabetical order."
   (let ((groups (cdr gnus-newsrc-alist))
        before)
     (while (and (not before) groups)
@@ -532,7 +592,7 @@ Can be used to turn version control on or off."
     (gnus-subscribe-newsgroup newgroup before)))
 
 (defun gnus-subscribe-hierarchically (newgroup)
-  "Subscribe new NEWSGROUP and insert it in hierarchical newsgroup order."
+  "Subscribe new NEWGROUP and insert it in hierarchical newsgroup order."
   ;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
   (save-excursion
     (set-buffer (nnheader-find-file-noselect gnus-current-startup-file))
@@ -557,7 +617,7 @@ Can be used to turn version control on or off."
   "Subscribe the new GROUP interactively.
 It is inserted in hierarchical newsgroup order if subscribed.  If not,
 it is killed."
-  (if (gnus-y-or-n-p (format "Subscribe new newsgroup: %s " group))
+  (if (gnus-y-or-n-p (format "Subscribe new newsgroup %s? " group))
       (gnus-subscribe-hierarchically group)
     (push group gnus-killed-list)))
 
@@ -571,15 +631,14 @@ it is killed."
 
 (defun gnus-subscribe-newsgroup (newsgroup &optional next)
   "Subscribe new NEWSGROUP.
-If NEXT is non-nil, it is inserted before NEXT.         Otherwise it is made
+If NEXT is non-nil, it is inserted before NEXT.  Otherwise it is made
 the first newsgroup."
   (save-excursion
     (goto-char (point-min))
     ;; We subscribe the group by changing its level to `subscribed'.
     (gnus-group-change-level
      newsgroup gnus-level-default-subscribed
-     gnus-level-killed (gnus-gethash (or next "dummy.group")
-                                    gnus-newsrc-hashtb))
+     gnus-level-killed (gnus-group-entry (or next "dummy.group")))
     (gnus-message 5 "Subscribe newsgroup: %s" newsgroup)
     (run-hook-with-args 'gnus-subscribe-newsgroup-hooks newsgroup)
     t))
@@ -601,17 +660,31 @@ the first newsgroup."
 (defvar gnus-newsgroup-unreads)
 (defvar nnoo-state-alist)
 (defvar gnus-current-select-method)
+(defvar mail-sources)
+(defvar nnmail-scan-directory-mail-source-once)
+(defvar nnmail-split-history)
+(defvar nnmail-spool-file)
+
+(defun gnus-close-all-servers ()
+  "Close all servers."
+  (interactive)
+  (dolist (server gnus-opened-servers)
+    (gnus-close-server (car server))))
 
 (defun gnus-clear-system ()
   "Clear all variables and buffers."
   ;; Clear Gnus variables.
-  (let ((variables gnus-variable-list))
+  (let ((variables (remove 'gnus-format-specs gnus-variable-list)))
     (while variables
       (set (car variables) nil)
       (setq variables (cdr variables))))
   ;; Clear other internal variables.
   (setq gnus-list-of-killed-groups nil
        gnus-have-read-active-file nil
+        gnus-agent-covered-methods nil
+        gnus-agent-file-loading-local nil
+        gnus-agent-file-loading-cache nil
+        gnus-server-method-cache nil
        gnus-newsrc-alist nil
        gnus-newsrc-hashtb nil
        gnus-killed-list nil
@@ -646,19 +719,19 @@ the first newsgroup."
     (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
   (gnus-kill-buffer nntp-server-buffer)
   ;; Kill Gnus buffers.
-  (let ((buffers (gnus-buffers)))
-    (when buffers
-      (mapcar 'kill-buffer buffers)))
+  (dolist (buffer (gnus-buffers))
+    (gnus-kill-buffer buffer))
   ;; Remove Gnus frames.
   (gnus-kill-gnus-frames))
 
 (defun gnus-no-server-1 (&optional arg slave)
   "Read network news.
-If ARG is a positive number, Gnus will use that as the
-startup level. If ARG is nil, Gnus will be started at level 2.
-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."
+If ARG is a positive number, Gnus will use that as the startup
+level.  If ARG is nil, Gnus will be started at level 2
+\(`gnus-level-default-subscribed' minus one).  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")
   (let ((val (or arg (1- gnus-level-default-subscribed))))
     (gnus val t slave)
@@ -668,7 +741,7 @@ As opposed to `gnus', this command will not connect to the local server."
 (defun gnus-1 (&optional arg dont-connect slave)
   "Read network news.
 If ARG is non-nil and a positive number, Gnus will use that as the
-startup level. If ARG is non-nil and not a positive number, Gnus will
+startup level.  If ARG is non-nil and not a positive number, Gnus will
 prompt the user for the name of an NNTP server to use."
   (interactive "P")
 
@@ -687,13 +760,21 @@ prompt the user for the name of an NNTP server to use."
     (setq gnus-slave slave)
     (gnus-read-init-file)
 
+    ;; Add "native" to gnus-predefined-server-alist just to have a
+    ;; name for the native select method.
+    (when gnus-select-method
+      (push (cons "native" gnus-select-method)
+           gnus-predefined-server-alist))
+    
+    (if gnus-agent
+       (gnus-agentize))
+
     (when gnus-simple-splash
       (setq gnus-simple-splash nil)
       (cond
        ((featurep 'xemacs)
        (gnus-xmas-splash))
-       ((and window-system
-            (= (frame-height) (1+ (window-height))))
+       (window-system
        (gnus-x-splash))))
 
     (let ((level (and (numberp arg) (> arg 0) arg))
@@ -717,12 +798,10 @@ prompt the user for the name of an NNTP server to use."
          (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))
-
          ;; Do the actual startup.
+         (if gnus-agent
+             (gnus-request-create-group "queue" '(nndraft "")))
+         (gnus-request-create-group "drafts" '(nndraft ""))
          (gnus-setup-news nil level dont-connect)
          (gnus-run-hooks 'gnus-setup-news-hook)
          (gnus-start-draft-setup)
@@ -736,23 +815,15 @@ prompt the user for the name of an NNTP server to use."
 (defun gnus-start-draft-setup ()
   "Make sure the draft group exists."
   (gnus-request-create-group "drafts" '(nndraft ""))
-  (unless (gnus-gethash "nndraft:drafts" gnus-newsrc-hashtb)
+  (unless (gnus-group-entry "nndraft:drafts")
     (let ((gnus-level-default-subscribed 1))
-      (gnus-subscribe-group "nndraft:drafts" nil '(nndraft "")))
+      (gnus-subscribe-group "nndraft:drafts" nil '(nndraft ""))))
+  (unless (equal (gnus-group-get-parameter "nndraft:drafts" 'gnus-dummy t)
+                '((gnus-draft-mode)))
+    (gnus-message 3 "Setting up drafts group")
     (gnus-group-set-parameter
      "nndraft:drafts" 'gnus-dummy '((gnus-draft-mode)))))
 
-;;;###autoload
-(defun gnus-unload ()
-  "Unload all Gnus features.
-\(For some value of `all' or `Gnus'.)  Currently, features whose names
-have prefixes `gnus-', `nn', `mm-' or `rfc' are unloaded.  Use
-cautiously -- unloading may cause trouble."
-  (interactive)
-  (dolist (feature features)
-    (if (string-match "^\\(gnus-\\|nn\\|mm-\\|rfc\\)" (symbol-name feature))
-       (unload-feature feature 'force))))
-
 \f
 ;;;
 ;;; Dribble file
@@ -779,7 +850,11 @@ cautiously -- unloading may cause trouble."
       (set-buffer gnus-dribble-buffer)
       (goto-char (point-max))
       (insert string "\n")
-      (set-window-point (get-buffer-window (current-buffer)) (point-max))
+      ;; This has been commented by Josh Huber <huber@alum.wpi.edu>
+      ;; It causes problems with both XEmacs and Emacs 21, and doesn't
+      ;; seem to be of much value. (FIXME: remove this after we make sure
+      ;; it's not needed).
+      ;; (set-window-point (get-buffer-window (current-buffer)) (point-max))
       (bury-buffer gnus-dribble-buffer)
       (save-excursion
        (set-buffer gnus-group-buffer)
@@ -797,6 +872,7 @@ cautiously -- unloading may cause trouble."
       (set-buffer (setq gnus-dribble-buffer
                        (gnus-get-buffer-create
                         (file-name-nondirectory dribble-file))))
+      (set (make-local-variable 'file-precious-flag) t)
       (erase-buffer)
       (setq buffer-file-name dribble-file)
       (auto-save-mode t)
@@ -805,6 +881,7 @@ cautiously -- unloading may cause trouble."
       (set-buffer-modified-p nil)
       (let ((auto (make-auto-save-file-name))
            (gnus-dribble-ignore t)
+           (purpose nil)
            modes)
        (when (or (file-exists-p auto) (file-exists-p dribble-file))
          ;; Load whichever file is newest -- the auto save file
@@ -819,11 +896,16 @@ cautiously -- unloading may cause trouble."
          (when (and (file-exists-p gnus-current-startup-file)
                     (file-exists-p dribble-file)
                     (setq modes (file-modes gnus-current-startup-file)))
-           (set-file-modes dribble-file modes))
+           (gnus-set-file-modes dribble-file modes))
+         (goto-char (point-min))
+         (when (search-forward "Gnus was exited on purpose" nil t)
+           (setq purpose t))
          ;; Possibly eval the file later.
          (when (or gnus-always-read-dribble-file
                    (gnus-y-or-n-p
-                    "Gnus auto-save file exists.  Do you want to read it? "))
+                    (if purpose
+                        "Gnus exited on purpose without saving; read auto-save file anyway? "
+                    "Gnus auto-save file exists.  Do you want to read it? ")))
            (setq gnus-dribble-eval-file t)))))))
 
 (defun gnus-dribble-eval-file ()
@@ -884,11 +966,34 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
       (gnus-read-newsrc-file rawfile))
 
     ;; Make sure the archive server is available to all and sundry.
-    (when gnus-message-archive-method
-      (setq gnus-server-alist (delq (assoc "archive" gnus-server-alist)
-                                   gnus-server-alist))
-      (push (cons "archive" gnus-message-archive-method)
-           gnus-server-alist))
+    (let ((method (or (and (stringp gnus-message-archive-method)
+                          (gnus-server-to-method
+                           gnus-message-archive-method))
+                     gnus-message-archive-method)))
+      ;; Check whether the archive method is writable.
+      (unless (or (not method)
+                 (stringp method)
+                 (memq 'respool (assoc (format "%s" (car method))
+                                       gnus-valid-select-methods)))
+       (setq method "archive")) ;; The default.
+      (when (stringp method)
+       (setq method `(nnfolder
+                      ,method
+                      (nnfolder-directory
+                       ,(nnheader-concat message-directory method))
+                      (nnfolder-active-file
+                       ,(nnheader-concat message-directory
+                                         (concat method "/active")))
+                      (nnfolder-get-new-mail nil)
+                      (nnfolder-inhibit-expiry t))))
+      (if (assoc "archive" gnus-server-alist)
+         (when gnus-update-message-archive-method
+           (if method
+               (setcdr (assoc "archive" gnus-server-alist) method)
+             (setq gnus-server-alist (delq (assoc "archive" gnus-server-alist)
+                                           gnus-server-alist))))
+       (when method
+         (push (cons "archive" method) gnus-server-alist))))
 
     ;; If we don't read the complete active file, we fill in the
     ;; hashtb here.
@@ -896,6 +1001,15 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
              (eq gnus-read-active-file 'some))
       (gnus-update-active-hashtb-from-killed))
 
+    ;; Validate agent covered methods now that gnus-server-alist has
+    ;; been initialized.
+    ;; NOTE: This is here for one purpose only.  By validating the
+    ;; agentized server's, it converts the old 5.10.3, and earlier,
+    ;; format to the current format.  That enables the agent code
+    ;; within gnus-read-active-file to function correctly.
+    (if gnus-agent
+        (gnus-agent-read-servers-validate))
+
     ;; Read the active file and create `gnus-active-hashtb'.
     ;; If `gnus-read-active-file' is nil, then we just create an empty
     ;; hash table.  The partial filling out of the hash table will be
@@ -939,10 +1053,19 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
               gnus-plugged)
       (gnus-find-new-newsgroups))
 
+    ;; Check and remove bogus newsgroups.
+    (when (and init gnus-check-bogus-newsgroups
+              gnus-read-active-file (not level)
+              (gnus-server-opened gnus-select-method))
+      (gnus-check-bogus-newsgroups))
+
     ;; We might read in new NoCeM messages here.
-    (when (and gnus-use-nocem
-              (not level)
-              (not dont-connect))
+    (when (and (not dont-connect)
+              gnus-use-nocem
+              (or (and (numberp gnus-use-nocem)
+                       (numberp level)
+                       (>= level gnus-use-nocem))
+                  (not level)))
       (gnus-nocem-scan-groups))
 
     ;; Read any slave files.
@@ -950,18 +1073,13 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
 
     ;; Find the number of unread articles in each non-dead group.
     (let ((gnus-read-active-file (and (not level) gnus-read-active-file)))
-      (gnus-get-unread-articles level))
-
-    (when (and init gnus-check-bogus-newsgroups
-              gnus-read-active-file (not level)
-              (gnus-server-opened gnus-select-method))
-      (gnus-check-bogus-newsgroups))))
+      (gnus-get-unread-articles level))))
 
 (defun gnus-call-subscribe-functions (method group)
   "Call METHOD to subscribe GROUP.
 If no function returns `non-nil', call `gnus-subscribe-zombies'."
   (unless (cond
-          ((gnus-functionp method)
+          ((functionp method)
            (funcall method group))
           ((listp method)
            (catch 'found
@@ -1006,7 +1124,7 @@ for new groups, and subscribe the new groups as zombies."
          (gnus-message 5 "Looking for new newsgroups...")
          (unless gnus-have-read-active-file
            (gnus-read-active-file))
-         (setq gnus-newsrc-last-checked-date (current-time-string))
+         (setq gnus-newsrc-last-checked-date (message-make-date))
          (unless gnus-killed-hashtb
            (gnus-make-hashtable-from-killed))
          ;; Go though every newsgroup in `gnus-active-hashtb' and compare
@@ -1071,7 +1189,8 @@ for new groups, and subscribe the new groups as zombies."
       (and regs (cdar regs))))))
 
 (defun gnus-ask-server-for-new-groups ()
-  (let* ((date (or gnus-newsrc-last-checked-date (current-time-string)))
+  (let* ((new-date (message-make-date))
+        (date (or gnus-newsrc-last-checked-date new-date))
         (methods (cons gnus-select-method
                        (nconc
                         (when (gnus-archive-server-wanted-p)
@@ -1081,7 +1200,6 @@ for new groups, and subscribe the new groups as zombies."
                               gnus-check-new-newsgroups)
                          gnus-secondary-select-methods))))
         (groups 0)
-        (new-date (current-time-string))
         group new-newsgroups got-new method hashtb
         gnus-override-subscribe-method)
     (unless gnus-killed-hashtb
@@ -1145,10 +1263,8 @@ for new groups, and subscribe the new groups as zombies."
   (catch 'ended
     ;; First check if any of the following files exist.  If they do,
     ;; it's not the first time the user has used Gnus.
-    (dolist (file (list gnus-current-startup-file
-                       (concat gnus-current-startup-file ".el")
+    (dolist (file (list (concat gnus-current-startup-file ".el")
                        (concat gnus-current-startup-file ".eld")
-                       gnus-startup-file
                        (concat gnus-startup-file ".el")
                        (concat gnus-startup-file ".eld")))
       (when (file-exists-p file)
@@ -1157,27 +1273,27 @@ for new groups, and subscribe the new groups as zombies."
     (unless (gnus-read-active-file-p)
       (let ((gnus-read-active-file t))
        (gnus-read-active-file)))
-    (setq gnus-newsrc-last-checked-date (current-time-string))
+    (setq gnus-newsrc-last-checked-date (message-make-date))
     ;; Subscribe to the default newsgroups.
     (let ((groups (or gnus-default-subscribed-newsgroups
                      gnus-backup-default-subscribed-newsgroups))
          group)
-      (when (eq groups t)
-       ;; If t, we subscribe (or not) all groups as if they were new.
-       (mapatoms
-        (lambda (sym)
-          (when (setq group (symbol-name sym))
-            (let ((do-sub (gnus-matches-options-n group)))
-              (cond
-               ((eq do-sub 'subscribe)
-                (gnus-sethash group group gnus-killed-hashtb)
-                (gnus-call-subscribe-functions
-                 gnus-subscribe-options-newsgroup-method group))
-               ((eq do-sub 'ignore)
-                nil)
-               (t
-                (push group gnus-killed-list))))))
-        gnus-active-hashtb)
+      (if (eq groups t)
+         ;; If t, we subscribe (or not) all groups as if they were new.
+         (mapatoms
+          (lambda (sym)
+            (when (setq group (symbol-name sym))
+              (let ((do-sub (gnus-matches-options-n group)))
+                (cond
+                 ((eq do-sub 'subscribe)
+                  (gnus-sethash group group gnus-killed-hashtb)
+                  (gnus-call-subscribe-functions
+                   gnus-subscribe-options-newsgroup-method group))
+                 ((eq do-sub 'ignore)
+                  nil)
+                 (t
+                  (push group gnus-killed-list))))))
+          gnus-active-hashtb)
        (dolist (group groups)
          ;; Only subscribe the default groups that are activated.
          (when (gnus-active group)
@@ -1185,12 +1301,14 @@ for new groups, and subscribe the new groups as zombies."
             group gnus-level-default-subscribed gnus-level-killed)))
        (save-excursion
          (set-buffer gnus-group-buffer)
-         (gnus-group-make-help-group))
+         ;; Don't error if the group already exists. This happens when a
+         ;; first-time user types 'F'. -- didier
+         (gnus-group-make-help-group t))
        (when gnus-novice-user
          (gnus-message 7 "`A k' to list killed groups"))))))
 
 (defun gnus-subscribe-group (group &optional previous method)
-  "Subcribe GROUP and put it after PREVIOUS."
+  "Subscribe GROUP and put it after PREVIOUS."
   (gnus-group-change-level
    (if method
        (list t group gnus-level-default-subscribed nil nil method)
@@ -1225,16 +1343,16 @@ for new groups, and subscribe the new groups as zombies."
     (when (and (stringp entry)
               oldlevel
               (< oldlevel gnus-level-zombie))
-      (setq entry (gnus-gethash entry gnus-newsrc-hashtb)))
+      (setq entry (gnus-group-entry entry)))
     (if (and (not oldlevel)
             (consp entry))
        (setq oldlevel (gnus-info-level (nth 2 entry)))
       (setq oldlevel (or oldlevel gnus-level-killed)))
     (when (stringp previous)
-      (setq previous (gnus-gethash previous gnus-newsrc-hashtb)))
+      (setq previous (gnus-group-entry previous)))
 
     (if (and (>= oldlevel gnus-level-zombie)
-            (gnus-gethash group gnus-newsrc-hashtb))
+            (gnus-group-entry group))
        ;; We are trying to subscribe a group that is already
        ;; subscribed.
        ()                              ; Do nothing.
@@ -1258,8 +1376,7 @@ for new groups, and subscribe the new groups as zombies."
                   entry)
          (gnus-sethash (car (nth 2 entry)) nil gnus-newsrc-hashtb)
          (when (nth 3 entry)
-           (setcdr (gnus-gethash (car (nth 3 entry))
-                                 gnus-newsrc-hashtb)
+           (setcdr (gnus-group-entry (car (nth 3 entry)))
                    (cdr entry)))
          (setcdr (cdr entry) (cdddr entry)))))
 
@@ -1319,7 +1436,7 @@ for new groups, and subscribe the new groups as zombies."
            (gnus-sethash group (cons num previous)
                          gnus-newsrc-hashtb))
          (when (cdr entry)
-           (setcdr (gnus-gethash (caadr entry) gnus-newsrc-hashtb) entry))
+           (setcdr (gnus-group-entry (caadr entry)) entry))
          (gnus-dribble-enter
           (format
            "(gnus-group-set-info '%S)" info)))))
@@ -1330,7 +1447,7 @@ for new groups, and subscribe the new groups as zombies."
 (defun gnus-kill-newsgroup (newsgroup)
   "Obsolete function.  Kills a newsgroup."
   (gnus-group-change-level
-   (gnus-gethash newsgroup gnus-newsrc-hashtb) gnus-level-killed))
+   (gnus-group-entry newsgroup) gnus-level-killed))
 
 (defun gnus-check-bogus-newsgroups (&optional confirm)
   "Remove bogus newsgroups.
@@ -1347,7 +1464,9 @@ newsgroup."
        (setq info (pop newsrc)
              group (gnus-info-group info))
        (unless (or (gnus-active group) ; Active
-                   (gnus-info-method info)) ; Foreign
+                   (and (gnus-info-method info)
+                        (not (gnus-secondary-method-p
+                              (gnus-