Importing Gnus v5.8.5.
[elisp/gnus.git-] / lisp / gnus-start.el
index 0159fb7..6a15660 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-start.el --- startup functions for Gnus
 ;;; gnus-start.el --- startup functions for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000
+;;        Free Software Foundation, Inc.
 
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -52,7 +53,7 @@ If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
               (directory-file-name installation-directory))
              "site-lisp/gnus-init")
     (error nil))
               (directory-file-name installation-directory))
              "site-lisp/gnus-init")
     (error nil))
-  "*The site-wide Gnus Emacs-Lisp startup file name, or nil if none.
+  "The site-wide Gnus Emacs-Lisp startup file name, or nil if none.
 If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
   :group 'gnus-start
   :type '(choice file (const nil)))
 If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
   :group 'gnus-start
   :type '(choice file (const nil)))
@@ -142,27 +143,19 @@ properly with all servers."
                 (const some)
                 (const t)))
 
                 (const some)
                 (const t)))
 
-(defcustom gnus-level-subscribed 5
-  "*Groups with levels less than or equal to this variable are subscribed."
-  :group 'gnus-group-levels
-  :type 'integer)
+(defconst gnus-level-subscribed 5
+  "Groups with levels less than or equal to this variable are subscribed.")
 
 
-(defcustom gnus-level-unsubscribed 7
-  "*Groups with levels less than or equal to this variable are unsubscribed.
+(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
 Groups with levels less than `gnus-level-subscribed', which should be
-less than this variable, are subscribed."
-  :group 'gnus-group-levels
-  :type 'integer)
+less than this variable, are subscribed.")
 
 
-(defcustom gnus-level-zombie 8
-  "*Groups with this level are zombie groups."
-  :group 'gnus-group-levels
-  :type 'integer)
+(defconst gnus-level-zombie 8
+  "Groups with this level are zombie groups.")
 
 
-(defcustom gnus-level-killed 9
-  "*Groups with this level are killed."
-  :group 'gnus-group-levels
-  :type 'integer)
+(defconst gnus-level-killed 9
+  "Groups with this level are killed.")
 
 (defcustom gnus-level-default-subscribed 3
   "*New subscribed groups will be subscribed at this level."
 
 (defcustom gnus-level-default-subscribed 3
   "*New subscribed groups will be subscribed at this level."
@@ -197,6 +190,16 @@ groups."
   :type '(choice integer
                 (const :tag "none" nil)))
 
   :type '(choice integer
                 (const :tag "none" nil)))
 
+(defcustom gnus-read-newsrc-file t
+  "*Non-nil means that Gnus will read the `.newsrc' file.
+Gnus always reads its own startup file, which is called
+\".newsrc.eld\".  The file called \".newsrc\" is in a format that can
+be readily understood by other newsreaders.  If you don't plan on
+using other newsreaders, set this variable to nil to save some time on
+entry."
+  :group 'gnus-newsrc
+  :type 'boolean)
+
 (defcustom gnus-save-newsrc-file t
   "*Non-nil means that Gnus will save the `.newsrc' file.
 Gnus always saves its own startup file, which is called
 (defcustom gnus-save-newsrc-file t
   "*Non-nil means that Gnus will save the `.newsrc' file.
 Gnus always saves its own startup file, which is called
@@ -223,12 +226,12 @@ not match this regexp will be removed before saving the list."
   :type 'boolean)
 
 (defcustom gnus-ignored-newsgroups
   :type 'boolean)
 
 (defcustom gnus-ignored-newsgroups
-  (purecopy (mapconcat 'identity
-                      '("^to\\."       ; not "real" groups
-                        "^[0-9. \t]+ " ; all digits in name
-                        "[][\"#'()]"   ; bogus characters
-                        )
-                      "\\|"))
+  (mapconcat 'identity
+            '("^to\\."                 ; not "real" groups
+              "^[0-9. \t]+ "           ; all digits in name
+              "^[\"][]\"[#'()]"        ; bogus characters
+              )
+            "\\|")
   "*A regexp to match uninteresting newsgroups in the active file.
 Any lines in the active file matching this regular expression are
 removed from the newsgroup list before anything else is done to it,
   "*A regexp to match uninteresting newsgroups in the active file.
 Any lines in the active file matching this regular expression are
 removed from the newsgroup list before anything else is done to it,
@@ -244,7 +247,9 @@ inserts new groups at the beginning of the list of groups;
 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;
 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;
-`gnus-subscribe-zombies' will make all new groups into zombies."
+`gnus-subscribe-zombies' will make all new groups into zombies;
+`gnus-subscribe-topics' will enter groups into the topics that
+claim them."
   :group 'gnus-group-new
   :type '(radio (function-item gnus-subscribe-randomly)
                (function-item gnus-subscribe-alphabetically)
   :group 'gnus-group-new
   :type '(radio (function-item gnus-subscribe-randomly)
                (function-item gnus-subscribe-alphabetically)
@@ -252,10 +257,9 @@ for your decision; `gnus-subscribe-killed' kills all new groups;
                (function-item gnus-subscribe-interactively)
                (function-item gnus-subscribe-killed)
                (function-item gnus-subscribe-zombies)
                (function-item gnus-subscribe-interactively)
                (function-item gnus-subscribe-killed)
                (function-item gnus-subscribe-zombies)
+               (function-item gnus-subscribe-topics)
                function))
 
                function))
 
-;; Suggested by a bug report by Hallvard B Furuseth.
-;; <h.b.furuseth@usit.uio.no>.
 (defcustom gnus-subscribe-options-newsgroup-method
   'gnus-subscribe-alphabetically
   "*This function is called to subscribe newsgroups mentioned on \"options -n\" lines.
 (defcustom gnus-subscribe-options-newsgroup-method
   'gnus-subscribe-alphabetically
   "*This function is called to subscribe newsgroups mentioned on \"options -n\" lines.
@@ -362,7 +366,7 @@ This hook is called as the first thing when Gnus is started."
 (defcustom gnus-after-getting-new-news-hook
   (when (gnus-boundp 'display-time-timer)
     '(display-time-event-handler))
 (defcustom gnus-after-getting-new-news-hook
   (when (gnus-boundp 'display-time-timer)
     '(display-time-event-handler))
-  "*A hook run after Gnus checks for new news."
+  "*A hook run after Gnus checks for new news when Gnus is already running."
   :group 'gnus-group-new
   :type 'hook)
 
   :group 'gnus-group-new
   :type 'hook)
 
@@ -383,10 +387,15 @@ Can be used to turn version control on or off."
   :group 'gnus-newsrc
   :type 'hook)
 
   :group 'gnus-newsrc
   :type 'hook)
 
-;;; Internal variables
+(defcustom gnus-always-read-dribble-file nil
+  "Unconditionally read the dribble file."
+  :group 'gnus-newsrc
+  :type 'boolean)
 
 
-(defvar gnus-always-read-dribble-file nil
-  "Uncoditionally read the dribble file.")
+(defvar gnus-startup-file-coding-system 'binary
+  "*Coding system for startup file.")
+
+;;; Internal variables
 
 (defvar gnus-newsrc-file-version nil)
 (defvar gnus-override-subscribe-method nil)
 
 (defvar gnus-newsrc-file-version nil)
 (defvar gnus-override-subscribe-method nil)
@@ -424,7 +433,9 @@ Can be used to turn version control on or off."
                   (file-exists-p (concat file ".el"))
                   (file-exists-p (concat file ".elc")))
               (condition-case var
                   (file-exists-p (concat file ".el"))
                   (file-exists-p (concat file ".elc")))
               (condition-case var
-                  (load file nil t)
+                  (let ((coding-system-for-read
+                         gnus-startup-file-coding-system))
+                    (load file nil t))
                 (error
                  (error "Error in %s: %s" file var)))))))))
 
                 (error
                  (error "Error in %s: %s" file var)))))))))
 
@@ -579,6 +590,7 @@ the first newsgroup."
 (defvar gnus-newsgroup-unreads)
 (defvar nnoo-state-alist)
 (defvar gnus-current-select-method)
 (defvar gnus-newsgroup-unreads)
 (defvar nnoo-state-alist)
 (defvar gnus-current-select-method)
+
 (defun gnus-clear-system ()
   "Clear all variables and buffers."
   ;; Clear Gnus variables.
 (defun gnus-clear-system ()
   "Clear all variables and buffers."
   ;; Clear Gnus variables.
@@ -622,8 +634,9 @@ the first newsgroup."
     (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
   (gnus-kill-buffer nntp-server-buffer)
   ;; Kill Gnus buffers.
     (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
   (gnus-kill-buffer nntp-server-buffer)
   ;; Kill Gnus buffers.
-  (while gnus-buffer-list
-    (gnus-kill-buffer (pop gnus-buffer-list)))
+  (let ((buffers (gnus-buffers)))
+    (when buffers
+      (mapcar 'kill-buffer buffers)))
   ;; Remove Gnus frames.
   (gnus-kill-gnus-frames))
 
   ;; Remove Gnus frames.
   (gnus-kill-gnus-frames))
 
@@ -655,8 +668,8 @@ prompt the user for the name of an NNTP server to use."
              (> arg 0)
              (max (car gnus-group-list-mode) arg))))
 
              (> arg 0)
              (max (car gnus-group-list-mode) arg))))
 
-    (gnus-splash)
     (gnus-clear-system)
     (gnus-clear-system)
+    (gnus-splash)
     (gnus-run-hooks 'gnus-before-startup-hook)
     (nnheader-init-server-buffer)
     (setq gnus-slave slave)
     (gnus-run-hooks 'gnus-before-startup-hook)
     (nnheader-init-server-buffer)
     (setq gnus-slave slave)
@@ -773,13 +786,12 @@ prompt the user for the name of an NNTP server to use."
   (let ((dribble-file (gnus-dribble-file-name)))
     (save-excursion
       (set-buffer (setq gnus-dribble-buffer
   (let ((dribble-file (gnus-dribble-file-name)))
     (save-excursion
       (set-buffer (setq gnus-dribble-buffer
-                       (get-buffer-create
+                       (gnus-get-buffer-create
                         (file-name-nondirectory dribble-file))))
                         (file-name-nondirectory dribble-file))))
-      (gnus-add-current-to-buffer-list)
       (erase-buffer)
       (setq buffer-file-name dribble-file)
       (auto-save-mode t)
       (erase-buffer)
       (setq buffer-file-name dribble-file)
       (auto-save-mode t)
-      (buffer-disable-undo (current-buffer))
+      (buffer-disable-undo)
       (bury-buffer (current-buffer))
       (set-buffer-modified-p nil)
       (let ((auto (make-auto-save-file-name))
       (bury-buffer (current-buffer))
       (set-buffer-modified-p nil)
       (let ((auto (make-auto-save-file-name))
@@ -849,7 +861,11 @@ prompt the user for the name of an NNTP server to use."
   "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."
   "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)))))
+  (require 'nnmail)
+  (let ((init (not (and gnus-newsrc-alist gnus-active-hashtb (not rawfile))))
+       ;; Binding this variable will inhibit multiple fetchings
+       ;; of the same mail source.
+       (nnmail-fetched-sources (list t)))
 
     (when init
       ;; Clear some variables to re-initialize news information.
 
     (when init
       ;; Clear some variables to re-initialize news information.
@@ -933,15 +949,27 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
 
 (defun gnus-find-new-newsgroups (&optional arg)
   "Search for new newsgroups and add them.
 
 (defun gnus-find-new-newsgroups (&optional arg)
   "Search for new newsgroups and add them.
-Each new newsgroup will be treated with `gnus-subscribe-newsgroup-method.'
+Each new newsgroup will be treated with `gnus-subscribe-newsgroup-method'.
 The `-n' option line from .newsrc is respected.
 The `-n' option line from .newsrc is respected.
-If ARG (the prefix), use the `ask-server' method to query the server
-for new groups."
-  (interactive "P")
-  (let ((check (if (or (and arg (not (listp gnus-check-new-newsgroups)))
-                      (null gnus-read-active-file)
-                      (eq gnus-read-active-file 'some))
-                  'ask-server gnus-check-new-newsgroups)))
+
+With 1 C-u, use the `ask-server' method to query the server for new
+groups.
+With 2 C-u's, use most complete method possible to query the server
+for new groups, and subscribe the new groups as zombies."
+  (interactive "p")
+  (let* ((gnus-subscribe-newsgroup-method
+         gnus-subscribe-newsgroup-method)
+        (check (cond
+                ((or (and (= (or arg 1) 4)
+                          (not (listp gnus-check-new-newsgroups)))
+                     (null gnus-read-active-file)
+                     (eq gnus-read-active-file 'some))
+                 'ask-server)
+                ((= (or arg 1) 16)
+                 (setq gnus-subscribe-newsgroup-method
+                       'gnus-subscribe-zombies)
+                 t)
+                (t gnus-check-new-newsgroups))))
     (unless (gnus-check-first-time-used)
       (if (or (consp check)
              (eq check 'ask-server))
     (unless (gnus-check-first-time-used)
       (if (or (consp check)
              (eq check 'ask-server))
@@ -1034,13 +1062,13 @@ 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)))
     ;; 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)
+      (setq new-newsgroups nil
+           gnus-override-subscribe-method method)
       (when (and (gnus-check-server method)
                 (gnus-request-newgroups date method))
        (save-excursion
       (when (and (gnus-check-server method)
                 (gnus-request-newgroups date method))
        (save-excursion
-         (setq got-new t)
-         (setq hashtb (gnus-make-hashtable 100))
+         (setq got-new t
+               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))
          (set-buffer nntp-server-buffer)
          ;; Enter all the new groups into a hashtable.
          (gnus-active-to-gnus-format method hashtb 'ignore))
@@ -1076,19 +1104,25 @@ for new groups."
         hashtb))
       (when new-newsgroups
        (gnus-subscribe-hierarchical-interactive new-newsgroups)))
         hashtb))
       (when new-newsgroups
        (gnus-subscribe-hierarchical-interactive new-newsgroups)))
-    (when (> groups 0)
-      (gnus-message 6 "%d new newsgroup%s arrived."
-                   groups (if (> groups 1) "s have" " has")))
+    (if (> groups 0)
+       (gnus-message 5 "%d new newsgroup%s arrived"
+                     groups (if (> groups 1) "s have" " has"))
+      (gnus-message 5 "No new newsgroups"))
     (when got-new
       (setq gnus-newsrc-last-checked-date new-date))
     got-new))
 
 (defun gnus-check-first-time-used ()
     (when got-new
       (setq gnus-newsrc-last-checked-date new-date))
     got-new))
 
 (defun gnus-check-first-time-used ()
-  (if (or (> (length gnus-newsrc-alist) 1)
-         (file-exists-p gnus-startup-file)
-         (file-exists-p (concat gnus-startup-file ".el"))
-         (file-exists-p (concat gnus-startup-file ".eld")))
-      nil
+  (catch 'ended
+    (let ((files (list gnus-current-startup-file
+                      (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"))))
+      (while files
+       (when (file-exists-p (pop files))
+         (throw 'ended nil))))
     (gnus-message 6 "First time user; subscribing you to default groups")
     (unless (gnus-read-active-file-p)
       (let ((gnus-read-active-file t))
     (gnus-message 6 "First time user; subscribing you to default groups")
     (unless (gnus-read-active-file-p)
       (let ((gnus-read-active-file t))
@@ -1118,16 +1152,21 @@ for new groups."
            (gnus-group-change-level
             (car groups) gnus-level-default-subscribed gnus-level-killed))
          (setq groups (cdr groups)))
            (gnus-group-change-level
             (car groups) gnus-level-default-subscribed gnus-level-killed))
          (setq groups (cdr groups)))
-       (gnus-group-make-help-group)
+       (save-excursion
+         (set-buffer gnus-group-buffer)
+         (gnus-group-make-help-group))
        (when gnus-novice-user
          (gnus-message 7 "`A k' to list killed groups"))))))
 
        (when gnus-novice-user
          (gnus-message 7 "`A k' to list killed groups"))))))
 
-(defun gnus-subscribe-group (group previous &optional method)
+
+(defun gnus-subscribe-group (group &optional previous method)
+  "Subcribe GROUP and put it after PREVIOUS."
   (gnus-group-change-level
    (if method
        (list t group gnus-level-default-subscribed nil nil method)
      group)
   (gnus-group-change-level
    (if method
        (list t group gnus-level-default-subscribed nil nil method)
      group)
-   gnus-level-default-subscribed gnus-level-killed previous t))
+   gnus-level-default-subscribed gnus-level-killed previous t)
+  t)
 
 ;; `gnus-group-change-level' is the fundamental function for changing
 ;; subscription levels of newsgroups.  This might mean just changing
 
 ;; `gnus-group-change-level' is the fundamental function for changing
 ;; subscription levels of newsgroups.  This might mean just changing
@@ -1222,14 +1261,14 @@ for new groups."
            (setq active (gnus-active group))
            (setq num
                  (if active (- (1+ (cdr active)) (car active)) t))
            (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)))))
+           ;; Shorten the select method if possible, if we need to
+           ;; store it at all (native groups).
+           (let ((method (gnus-method-simplify
+                          (or gnus-override-subscribe-method
+                              (gnus-group-method group)))))
+             (if method
+                 (setq info (list group level nil nil method))
+               (setq info (list group level nil)))))
          (unless previous
            (setq previous
                  (let ((p gnus-newsrc-alist))
          (unless previous
            (setq previous
                  (let ((p gnus-newsrc-alist))
@@ -1347,7 +1386,7 @@ newsgroup."
           t)
         (condition-case ()
             (inline (gnus-request-group group dont-check method))
           t)
         (condition-case ()
             (inline (gnus-request-group group dont-check method))
-          (error nil)
+          ;;(error nil)
           (quit nil))
         (setq active (gnus-parse-active))
         ;; If there are no articles in the group, the GROUP
           (quit nil))
         (setq active (gnus-parse-active))
         ;; If there are no articles in the group, the GROUP
@@ -1370,6 +1409,7 @@ newsgroup."
                info (inline (gnus-find-method-for-group
                              (gnus-info-group info)))))
       (gnus-activate-group (gnus-info-group info) nil t))
                info (inline (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.
     (let* ((range (gnus-info-read info))
           (num 0))
       ;; If a cache is present, we may have to alter the active info.
@@ -1418,7 +1458,7 @@ newsgroup."
        ;; Then we want to peel off any elements that are higher
        ;; than the upper active limit.
        (let ((srange range))
        ;; Then we want to peel off any elements that are higher
        ;; than the upper active limit.
        (let ((srange range))
-         ;; Go past all legal elements.
+         ;; Go past all valid elements.
          (while (and (cdr srange)
                      (<= (or (and (atom (cadr srange))
                                   (cadr srange))
          (while (and (cdr srange)
                      (<= (or (and (atom (cadr srange))
                                   (cadr srange))
@@ -1426,7 +1466,7 @@ newsgroup."
                          (cdr active)))
            (setq srange (cdr srange)))
          (when (cdr srange)
                          (cdr active)))
            (setq srange (cdr srange)))
          (when (cdr srange)
-           ;; Nuke all remaining illegal elements.
+           ;; Nuke all remaining invalid elements.
            (setcdr srange nil))
 
          ;; Adjust the final element.
            (setcdr srange nil))
 
          ;; Adjust the final element.
@@ -1460,7 +1500,7 @@ newsgroup."
                  gnus-activate-foreign-newsgroups)
                 (t 0))
           level))
                  gnus-activate-foreign-newsgroups)
                 (t 0))
           level))
-        info group active method)
+        scanned-methods info group active method retrievegroups)
     (gnus-message 5 "Checking new news...")
 
     (while newsrc
     (gnus-message 5 "Checking new news...")
 
     (while newsrc
@@ -1472,6 +1512,13 @@ newsgroup."
       ;; be reached) we just set the number of unread articles in this
       ;; newsgroup to t.  This means that Gnus thinks that there are
       ;; unread articles, but it has no idea how many.
       ;; be reached) we just set the number of unread articles in this
       ;; newsgroup to t.  This means that Gnus thinks that there are
       ;; unread articles, but it has no idea how many.
+
+      ;; To be more explicit:
+      ;; >0 for an active group with messages
+      ;; 0 for an active group with no unread messages
+      ;; nil for non-foreign groups that the user has requested not be checked
+      ;; t for unchecked foreign groups or bogus groups, or groups that can't
+      ;;   be checked, for one reason or other.
       (if (and (setq method (gnus-info-method info))
               (not (inline
                      (gnus-server-equal
       (if (and (setq method (gnus-info-method info))
               (not (inline
                      (gnus-server-equal
@@ -1481,24 +1528,80 @@ newsgroup."
          ;; These groups are foreign.  Check the level.
          (when (<= (gnus-info-level info) foreign-level)
            (setq active (gnus-activate-group group 'scan))
          ;; These groups are foreign.  Check the level.
          (when (<= (gnus-info-level info) foreign-level)
            (setq active (gnus-activate-group group 'scan))
+           ;; Let the Gnus agent save the active file.
+           (when (and gnus-agent gnus-plugged active)
+             (gnus-agent-save-group-info
+              method (gnus-group-real-name group) active))
            (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.
            (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.
-       (when (and (<= (gnus-info-level info) level)
-                  (not gnus-read-active-file))
-         (setq active (gnus-activate-group group 'scan))
-         (inline (gnus-close-group group))))
+       (cond
+        ;; We don't want these groups.
+        ((> (gnus-info-level info) level)
+         (setq active 'ignore))
+        ;; Activate groups.
+        ((not gnus-read-active-file)
+         (if (gnus-check-backend-function 'retrieve-groups group)
+             ;; if server support gnus-retrieve-groups we push
+             ;; the group onto retrievegroups for later checking
+             (if (assoc method retrievegroups)
+                 (setcdr (assoc method retrievegroups)
+                         (cons group (cdr (assoc method retrievegroups))))
+               (push (list method group) retrievegroups))
+           ;; hack: `nnmail-get-new-mail' changes the mail-source depending
+           ;; on the group, so we must perform a scan for every group
+           ;; if the users has any directory mail sources.
+           (if (and (null (assq 'directory
+                                (or mail-sources
+                                    (if (listp nnmail-spool-file) 
+                                        nnmail-spool-file
+                                      (list nnmail-spool-file)))))
+                    (member method scanned-methods))
+               (setq active (gnus-activate-group group))
+             (setq active (gnus-activate-group group 'scan))
+             (push method scanned-methods))
+           (inline (gnus-close-group group))))))
 
       ;; Get the number of unread articles in the group.
 
       ;; Get the number of unread articles in the group.
-      (if active
-         (inline (gnus-get-unread-articles-in-group info active t))
+      (cond
+       ((eq active 'ignore)
+       ;; Don't do anything.
+       )
+       (active
+       (inline (gnus-get-unread-articles-in-group info active t)))
+       (t
        ;; The group couldn't be reached, so we nix out the number of
        ;; unread articles and stuff.
        (gnus-set-active group nil)
        ;; 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)))
+       (let ((tmp (gnus-gethash group gnus-newsrc-hashtb)))
+         (if tmp (setcar tmp t))))))
+
+    ;; iterate through groups on methods which support gnus-retrieve-groups
+    ;; and fetch a partial active file and use it to find new news.
+    (while retrievegroups
+      (let* ((mg (pop retrievegroups))
+            (method (or (car mg) gnus-select-method))
+            (groups (cdr mg)))
+       (gnus-check-server method)
+       ;; Request that the backend scan its incoming messages.
+       (when (gnus-check-backend-function 'request-scan (car method))
+         (gnus-request-scan nil method))
+       (gnus-read-active-file-2 (mapcar (lambda (group)
+                                          (gnus-group-real-name group))
+                                        groups) method)
+       (dolist (group groups)
+         (cond
+          ((setq active (gnus-active (gnus-info-group
+                                      (setq info (gnus-get-info group)))))
+           (inline (gnus-get-unread-articles-in-group info active t)))
+          (t
+           ;; 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))))))
 
     (gnus-message 5 "Checking new news...done")))
 
 
     (gnus-message 5 "Checking new news...done")))
 
@@ -1606,87 +1709,91 @@ newsgroup."
 (defun gnus-read-active-file (&optional force not-native)
   (gnus-group-set-mode-line)
   (let ((methods
 (defun gnus-read-active-file (&optional force not-native)
   (gnus-group-set-mode-line)
   (let ((methods
-        (append
-         (if (and (not not-native)
-                  (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-archive-server-wanted-p)
-           (list "archive"))))
-       list-type)
+        (mapcar
+         (lambda (m) (if (stringp m) (gnus-server-get-method nil m) m))
+         (append
+          (if (and (not not-native)
+                   (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-archive-server-wanted-p)
+            (list "archive")))))
+       method)
     (setq gnus-have-read-active-file nil)
     (save-excursion
       (set-buffer nntp-server-buffer)
     (setq gnus-have-read-active-file nil)
     (save-excursion
       (set-buffer nntp-server-buffer)
-      (while 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))))
+      (while (setq method (pop methods))
+       ;; Only do each method once, in case the methods appear more
+       ;; than once in this list.
+       (unless (member method methods)
+         (condition-case ()
+             (gnus-read-active-file-1 method force)
+           ;; We catch C-g so that we can continue past servers
+           ;; that do not respond.
+           (quit nil)))))))
+
+(defun gnus-read-active-file-1 (method force)
+  (let (where mesg)
+    (setq 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)
+    (when (gnus-check-server method)
+      ;; Request that the backend scan its incoming messages.
+      (when (gnus-check-backend-function 'request-scan (car method))
+       (gnus-request-scan nil method))
+      (cond
+       ((and (eq gnus-read-active-file 'some)
+            (gnus-check-backend-function 'retrieve-groups (car method))
+            (not force))
+       (let ((newsrc (cdr gnus-newsrc-alist))
+             (gmethod (gnus-server-get-method nil method))
+             groups info)
+         (while (setq info (pop newsrc))
+           (when (inline
+                   (gnus-server-equal
+                    (inline
+                      (gnus-find-method-for-group
+                       (gnus-info-group info) info))
+                    gmethod))
+             (push (gnus-group-real-name (gnus-info-group info))
+                   groups)))
+         (gnus-read-active-file-2 groups method)))
+       ((null method)
+       t)
+       (t
+       (if (not (gnus-request-list 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-message 5 mesg)
-         (when (gnus-check-server method)
-           ;; Request that the backend scan its incoming messages.
-           (when (gnus-check-backend-function 'request-scan (car method))
-             (gnus-request-scan nil method))
-           (cond
-            ((and (eq gnus-read-active-file 'some)
-                  (gnus-check-backend-function 'retrieve-groups (car method))
-                  (not force))
-             (let ((newsrc (cdr gnus-newsrc-alist))
-                   (gmethod (gnus-server-get-method nil method))
-                   groups info)
-               (while (setq info (pop newsrc))
-                 (when (inline
-                         (gnus-server-equal
-                          (inline
-                            (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 nil t))
-                  (t
-                   (gnus-groups-to-gnus-format
-                    method gnus-active-hashtb t))))))
-            ((null method)
-             t)
-            (t
-             (if (not (gnus-request-list 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 nil t)
-               ;; We mark this active file as read.
-               (push method gnus-have-read-active-file)
-               (gnus-message 5 "%sdone" mesg))))))
-       (setq methods (cdr methods))))))
-
-
-(defun gnus-ignored-newsgroups-has-to-p ()
-  "T only when gnus-ignored-newsgroups includes \"^to\\\\.\" as an element."
-  ;; note this regexp is the same as:
-  ;; (concat (regexp-quote "^to\\.") "\\($\\|" (regexp-quote "\\|") "\\)")
-  (string-match "\\^to\\\\\\.\\($\\|\\\\|\\)"
-               gnus-ignored-newsgroups))
-
+         (gnus-active-to-gnus-format method gnus-active-hashtb nil t)
+         ;; We mark this active file as read.
+         (push method gnus-have-read-active-file)
+         (gnus-message 5 "%sdone" mesg)))))))
+
+(defun gnus-read-active-file-2 (groups method)
+  "Read an active file for GROUPS in METHOD using gnus-retrieve-groups."
+  (when groups
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (gnus-check-server method)
+      (let ((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 nil t))
+             (t
+              (gnus-groups-to-gnus-format method gnus-active-hashtb t)))))))
+  
 ;; Read an active file and place the results in `gnus-active-hashtb'.
 (defun gnus-active-to-gnus-format (&optional method hashtb ignore-errors
                                             real-active)
 ;; Read an active file and place the results in `gnus-active-hashtb'.
 (defun gnus-active-to-gnus-format (&optional method hashtb ignore-errors
                                             real-active)
@@ -1704,22 +1811,22 @@ newsgroup."
                              (gnus-make-hashtable 4096)))))))
     ;; Delete unnecessary lines.
     (goto-char (point-min))
                              (gnus-make-hashtable 4096)))))))
     ;; Delete unnecessary lines.
     (goto-char (point-min))
-    (cond ((gnus-ignored-newsgroups-has-to-p)
-          (delete-matching-lines gnus-ignored-newsgroups))
-         ((string= gnus-ignored-newsgroups "")
-          (delete-matching-lines "^to\\."))
-         (t
-          (delete-matching-lines (concat "^to\\.\\|"
-                                         gnus-ignored-newsgroups))))
-
-    ;; Make the group names readable as a lisp expression even if they
-    ;; contain special characters.
-    (goto-char (point-max))
-    (while (re-search-backward "[][';?()#]" nil t)
-      (insert ?\\))
+    (cond
+     ((string= gnus-ignored-newsgroups "")
+      (delete-matching-lines "^to\\."))
+     (t
+      (delete-matching-lines (concat "^to\\.\\|" gnus-ignored-newsgroups))))
+
+    (goto-char (point-min))
+    (unless (re-search-forward "[\\\"]" nil t)
+      ;; Make the group names readable as a lisp expression even if they
+      ;; contain special characters.
+      (goto-char (point-max))
+      (while (re-search-backward "[][';?()#]" nil t)
+       (insert ?\\)))
 
     ;; Let the Gnus agent save the active file.
 
     ;; Let the Gnus agent save the active file.
-    (when (and gnus-agent real-active)
+    (when (and gnus-agent real-active gnus-plugged)
       (gnus-agent-save-active method))
 
     ;; If these are groups from a foreign select method, we insert the
       (gnus-agent-save-active method))
 
     ;; If these are groups from a foreign select method, we insert the
@@ -1730,30 +1837,37 @@ newsgroup."
       (let ((prefix (gnus-group-prefixed-name "" method)))
        (goto-char (point-min))
        (while (and (not (eobp))
       (let ((prefix (gnus-group-prefixed-name "" method)))
        (goto-char (point-min))
        (while (and (not (eobp))
-                   (progn (insert prefix)
-                          (zerop (forward-line 1)))))))
+                   (progn
+                     (when (= (following-char) ?\")
+                       (forward-char 1))
+                     (insert prefix)
+                     (zerop (forward-line 1)))))))
     ;; Store the active file in a hash table.
     (goto-char (point-min))
     (let (group max min)
       (while (not (eobp))
     ;; Store the active file in a hash table.
     (goto-char (point-min))
     (let (group max min)
       (while (not (eobp))
-       (condition-case ()
+       (condition-case err
            (progn
              (narrow-to-region (point) (gnus-point-at-eol))
              ;; group gets set to a symbol interned in the hash table
              ;; (what a hack!!) - jwz
              (setq group (let ((obarray hashtb)) (read cur)))
            (progn
              (narrow-to-region (point) (gnus-point-at-eol))
              ;; group gets set to a symbol interned in the hash table
              ;; (what a hack!!) - jwz
              (setq group (let ((obarray hashtb)) (read cur)))
+             ;; ### The extended group name scheme makes
+             ;; the previous optimization strategy sort of pointless...
+             (when (stringp group)
+               (setq group (intern group hashtb)))
              (if (and (numberp (setq max (read cur)))
                       (numberp (setq min (read cur)))
                       (progn
                         (skip-chars-forward " \t")
                         (not
              (if (and (numberp (setq max (read cur)))
                       (numberp (setq min (read cur)))
                       (progn
                         (skip-chars-forward " \t")
                         (not
-                         (or (= (following-char) ?=)
-                             (= (following-char) ?x)
-                             (= (following-char) ?j)))))
+                         (or (eq (char-after) ?=)
+                             (eq (char-after) ?x)
+                             (eq (char-after) ?j)))))
                  (progn
                    (set group (cons min max))
                    ;; if group is moderated, stick in moderation table
                  (progn
                    (set group (cons min max))
                    ;; if group is moderated, stick in moderation table
-                   (when (= (following-char) ?m)
+                   (when (eq (char-after) ?m)
                      (unless gnus-moderated-hashtb
                        (setq gnus-moderated-hashtb (gnus-make-hashtable)))
                      (gnus-sethash (symbol-name group) t
                      (unless gnus-moderated-hashtb
                        (setq gnus-moderated-hashtb (gnus-make-hashtable)))
                      (gnus-sethash (symbol-name group) t
@@ -1764,7 +1878,7 @@ newsgroup."
                (symbolp group)
                (set group nil))
           (unless ignore-errors
                (symbolp group)
                (set group nil))
           (unless ignore-errors
-            (gnus-message 3 "Warning - illegal active: %s"
+            (gnus-message 3 "Warning - invalid active: %s"
                           (buffer-substring
                            (gnus-point-at-bol) (gnus-point-at-eol))))))
        (widen)
                           (buffer-substring
                            (gnus-point-at-bol) (gnus-point-at-eol))))))
        (widen)
@@ -1786,39 +1900,44 @@ newsgroup."
                     (gnus-group-prefixed-name "" method))))
 
     ;; Let the Gnus agent save the active file.
                     (gnus-group-prefixed-name "" method))))
 
     ;; Let the Gnus agent save the active file.
-    (when (and gnus-agent real-active)
-      (gnus-agent-save-groups method))
-    
-    (goto-char (point-min))
-    ;; We split this into to separate loops, one with the prefix
-    ;; and one without to speed the reading up somewhat.
-    (if prefix
-       (let (min max opoint group)
+    (if (and gnus-agent
+            real-active
+            gnus-plugged
+            (gnus-agent-method-p method))
+       (progn
+         (gnus-agent-save-groups method)
+         (gnus-active-to-gnus-format method hashtb nil real-active))
+
+      (goto-char (point-min))
+      ;; We split this into to separate loops, one with the prefix
+      ;; and one without to speed the reading up somewhat.
+      (if prefix
+         (let (min max opoint group)
+           (while (not (eobp))
+             (condition-case ()
+                 (progn
+                   (read cur) (read cur)
+                   (setq min (read cur)
+                         max (read cur)
+                         opoint (point))
+                   (skip-chars-forward " \t")
+                   (insert prefix)
+                   (goto-char opoint)
+                   (set (let ((obarray hashtb)) (read cur))
+                        (cons min max)))
+               (error (and group (symbolp group) (set group nil))))
+             (forward-line 1)))
+       (let (min max group)
          (while (not (eobp))
            (condition-case ()
          (while (not (eobp))
            (condition-case ()
-               (progn
+               (when (eq (char-after) ?2)
                  (read cur) (read cur)
                  (setq min (read cur)
                  (read cur) (read cur)
                  (setq min (read cur)
-                       max (read cur)
-                       opoint (point))
-                 (skip-chars-forward " \t")
-                 (insert prefix)
-                 (goto-char opoint)
-                 (set (let ((obarray hashtb)) (read cur))
+                       max (read cur))
+                 (set (setq group (let ((obarray hashtb)) (read cur)))
                       (cons min max)))
              (error (and group (symbolp group) (set group nil))))
                       (cons min max)))
              (error (and group (symbolp group) (set group nil))))
-           (forward-line 1)))
-      (let (min max group)
-       (while (not (eobp))
-         (condition-case ()
-             (when (= (following-char) ?2)
-               (read cur) (read cur)
-               (setq min (read cur)
-                     max (read cur))
-               (set (setq group (let ((obarray hashtb)) (read cur)))
-                    (cons min max)))
-           (error (and group (symbolp group) (set group nil))))
-         (forward-line 1))))))
+           (forward-line 1)))))))
 
 (defun gnus-read-newsrc-file (&optional force)
   "Read startup file.
 
 (defun gnus-read-newsrc-file (&optional force)
   "Read startup file.
@@ -1836,7 +1955,8 @@ 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)
 
       ;; file (ticked articles, killed groups, foreign methods, etc.)
       (gnus-read-newsrc-el-file quick-file)
 
-      (when (and (file-exists-p gnus-current-startup-file)
+      (when (and gnus-read-newsrc-file
+                (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
                 (or force
                     (and (file-newer-than-file-p newsrc-file quick-file)
                          (file-newer-than-file-p newsrc-file
@@ -1852,7 +1972,7 @@ If FORCE is non-nil, the .newsrc file is read."
        (save-excursion
          (gnus-message 5 "Reading %s..." newsrc-file)
          (set-buffer (nnheader-find-file-noselect newsrc-file))
        (save-excursion
          (gnus-message 5 "Reading %s..." newsrc-file)
          (set-buffer (nnheader-find-file-noselect newsrc-file))
-         (buffer-disable-undo (current-buffer))
+         (buffer-disable-undo)
          (gnus-newsrc-to-gnus-format)
          (kill-buffer (current-buffer))
          (gnus-message 5 "Reading %s...done" newsrc-file)))
          (gnus-newsrc-to-gnus-format)
          (kill-buffer (current-buffer))
          (gnus-message 5 "Reading %s...done" newsrc-file)))
@@ -1892,7 +2012,8 @@ If FORCE is non-nil, the .newsrc file is read."
     (gnus-message 5 "Reading %s..." ding-file)
     (let (gnus-newsrc-assoc)
       (condition-case nil
     (gnus-message 5 "Reading %s..." ding-file)
     (let (gnus-newsrc-assoc)
       (condition-case nil
-         (load ding-file t t t)
+         (let ((coding-system-for-read gnus-startup-file-coding-system))
+           (load ding-file t t t))
        (error
         (ding)
         (unless (gnus-yes-or-no-p
        (error
         (ding)
         (unless (gnus-yes-or-no-p
@@ -1970,7 +2091,8 @@ If FORCE is non-nil, the .newsrc file is read."
     (if (or (file-exists-p real-file)
            (file-exists-p (concat real-file ".el"))
            (file-exists-p (concat real-file ".eld")))
     (if (or (file-exists-p real-file)
            (file-exists-p (concat real-file ".el"))
            (file-exists-p (concat real-file ".eld")))
-       real-file file)))
+       real-file
+      file)))
 
 (defun gnus-newsrc-to-gnus-format ()
   (setq gnus-newsrc-options "")
 
 (defun gnus-newsrc-to-gnus-format ()
   (setq gnus-newsrc-options "")
@@ -2026,7 +2148,7 @@ If FORCE is non-nil, the .newsrc file is read."
        (unless (boundp symbol)
          (set symbol nil))
        ;; It was a group name.
        (unless (boundp symbol)
          (set symbol nil))
        ;; It was a group name.
-       (setq subscribed (= (following-char) ?:)
+       (setq subscribed (eq (char-after) ?:)
              group (symbol-name symbol)
              reads nil)
        (if (eolp)
              group (symbol-name symbol)
              reads nil)
        (if (eolp)
@@ -2050,7 +2172,7 @@ If FORCE is non-nil, the .newsrc file is read."
                           (read buf)))
              (widen)
              ;; If the next character is a dash, then this is a range.
                           (read buf)))
              (widen)
              ;; If the next character is a dash, then this is a range.
-             (if (= (following-char) ?-)
+             (if (eq (char-after) ?-)
                  (progn
                    ;; We read the upper bound of the range.
                    (forward-char 1)
                  (progn
                    ;; We read the upper bound of the range.
                    (forward-char 1)
@@ -2072,8 +2194,8 @@ If FORCE is non-nil, the .newsrc file is read."
                (push num1 reads))
              ;; If the next char in ?\n, then we have reached the end
              ;; of the line and return nil.
                (push num1 reads))
              ;; If the next char in ?\n, then we have reached the end
              ;; of the line and return nil.
-             (/= (following-char) ?\n))
-            ((= (following-char) ?\n)
+             (not (eq (char-after) ?\n)))
+            ((eq (char-after) ?\n)
              ;; End of line, so we end.
              nil)
             (t
              ;; End of line, so we end.
              nil)
             (t
@@ -2087,7 +2209,7 @@ If FORCE is non-nil, the .newsrc file is read."
                            (buffer-substring (gnus-point-at-bol)
                                              (gnus-point-at-eol))))
              nil))
                            (buffer-substring (gnus-point-at-bol)
                                              (gnus-point-at-eol))))
              nil))
-         ;; Skip past ", ".  Spaces are illegal in these ranges, but
+         ;; Skip past ", ".  Spaces are invalid in these ranges, but
          ;; we allow them, because it's a common mistake to put a
          ;; space after the comma.
          (skip-chars-forward ", "))
          ;; we allow them, because it's a common mistake to put a
          ;; space after the comma.
          (skip-chars-forward ", "))
@@ -2199,7 +2321,7 @@ If FORCE is non-nil, the .newsrc file is read."
                  (gnus-point-at-eol)))
        ;; Search for all "words"...
        (while (re-search-forward "[^ \t,\n]+" eol t)
                  (gnus-point-at-eol)))
        ;; Search for all "words"...
        (while (re-search-forward "[^ \t,\n]+" eol t)
-         (if (= (char-after (match-beginning 0)) ?!)
+         (if (eq (char-after (match-beginning 0)) ?!)
              ;; If the word begins with a bang (!), this is a "not"
              ;; spec.  We put this spec (minus the bang) and the
              ;; symbol `ignore' into the list.
              ;; If the word begins with a bang (!), this is a "not"
              ;; spec.  We put this spec (minus the bang) and the
              ;; symbol `ignore' into the list.
@@ -2241,19 +2363,19 @@ If FORCE is non-nil, the .newsrc file is read."
            (gnus-gnus-to-newsrc-format)
            (gnus-message 8 "Saving %s...done" gnus-current-startup-file))
          ;; Save .newsrc.eld.
            (gnus-gnus-to-newsrc-format)
            (gnus-message 8 "Saving %s...done" gnus-current-startup-file))
          ;; Save .newsrc.eld.
-         (set-buffer (get-buffer-create " *Gnus-newsrc*"))
+         (set-buffer (gnus-get-buffer-create " *Gnus-newsrc*"))
          (make-local-variable 'version-control)
          (setq version-control 'never)
          (setq buffer-file-name
                (concat gnus-current-startup-file ".eld"))
          (setq default-directory (file-name-directory buffer-file-name))
          (make-local-variable 'version-control)
          (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))
+         (buffer-disable-undo)
          (erase-buffer)
          (gnus-message 5 "Saving %s.eld..." gnus-current-startup-file)
          (gnus-gnus-to-quick-newsrc-format)
          (gnus-run-hooks 'gnus-save-quick-newsrc-hook)
          (erase-buffer)
          (gnus-message 5 "Saving %s.eld..." gnus-current-startup-file)
          (gnus-gnus-to-quick-newsrc-format)
          (gnus-run-hooks 'gnus-save-quick-newsrc-hook)
-         (save-buffer)
+         (let ((coding-system-for-write gnus-startup-file-coding-system))
+           (save-buffer))
          (kill-buffer (current-buffer))
          (gnus-message
           5 "Saving %s.eld...done" gnus-current-startup-file))
          (kill-buffer (current-buffer))
          (gnus-message
           5 "Saving %s.eld...done" gnus-current-startup-file))
@@ -2264,6 +2386,7 @@ If FORCE is non-nil, the .newsrc file is read."
   "Insert Gnus variables such as gnus-newsrc-alist in lisp format."
   (let ((print-quoted t)
        (print-escape-newlines t))
   "Insert Gnus variables such as gnus-newsrc-alist in lisp format."
   (let ((print-quoted t)
        (print-escape-newlines t))
+
     (insert ";; -*- emacs-lisp -*-\n")
     (insert ";; Gnus startup file.\n")
     (insert "\
     (insert ";; -*- emacs-lisp -*-\n")
     (insert ";; Gnus startup file.\n")
     (insert "\
@@ -2311,7 +2434,7 @@ If FORCE is non-nil, the .newsrc file is read."
          info ranges range method)
       (setq buffer-file-name gnus-current-startup-file)
       (setq default-directory (file-name-directory buffer-file-name))
          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))
+      (buffer-disable-undo)
       (erase-buffer)
       ;; Write options.
       (when gnus-newsrc-options
       (erase-buffer)
       ;; Write options.
       (when gnus-newsrc-options
@@ -2363,6 +2486,13 @@ If FORCE is non-nil, the .newsrc file is read."
 ;;; Slave functions.
 ;;;
 
 ;;; Slave functions.
 ;;;
 
+(defvar gnus-slave-mode nil)
+
+(defun gnus-slave-mode ()
+  "Minor mode for slave Gnusae."
+  (gnus-add-minor-mode 'gnus-slave-mode " Slave" (make-sparse-keymap))
+  (gnus-run-hooks 'gnus-slave-mode-hook))
+
 (defun gnus-slave-save-newsrc ()
   (save-excursion
     (set-buffer gnus-dribble-buffer)
 (defun gnus-slave-save-newsrc ()
   (save-excursion
     (set-buffer gnus-dribble-buffer)
@@ -2389,8 +2519,7 @@ If FORCE is non-nil, the .newsrc file is read."
        ()                              ; There are no slave files to read.
       (gnus-message 7 "Reading slave newsrcs...")
       (save-excursion
        ()                              ; There are no slave files to read.
       (gnus-message 7 "Reading slave newsrcs...")
       (save-excursion
-       (set-buffer (get-buffer-create " *gnus slave*"))
-       (buffer-disable-undo (current-buffer))
+       (set-buffer (gnus-get-buffer-create " *gnus slave*"))
        (setq slave-files
              (sort (mapcar (lambda (file)
                              (list (nth 5 (file-attributes file)) file))
        (setq slave-files
              (sort (mapcar (lambda (file)
                              (list (nth 5 (file-attributes file)) file))
@@ -2448,6 +2577,8 @@ If FORCE is non-nil, the .newsrc file is read."
 
     (gnus-message 5 "Reading descriptions file via %s..." (car method))
     (cond
 
     (gnus-message 5 "Reading descriptions file via %s..." (car method))
     (cond
+     ((null (gnus-get-function method 'request-list-newsgroups t))
+      t)
      ((not (gnus-check-server method))
       (gnus-message 1 "Couldn't open server")
       nil)
      ((not (gnus-check-server method))
       (gnus-message 1 "Couldn't open server")
       nil)
@@ -2492,12 +2623,13 @@ If FORCE is non-nil, the .newsrc file is read."
              (let ((str (buffer-substring
                          (point) (progn (end-of-line) (point))))
                    (coding
              (let ((str (buffer-substring
                          (point) (progn (end-of-line) (point))))
                    (coding
-                    (and (boundp 'enable-multibyte-characters)
-                         enable-multibyte-characters
+                    (and (or gnus-xemacs
+                             (and (boundp 'enable-multibyte-characters)
+                                  enable-multibyte-characters))
                          (fboundp 'gnus-mule-get-coding-system)
                          (gnus-mule-get-coding-system (symbol-name group)))))
                          (fboundp 'gnus-mule-get-coding-system)
                          (gnus-mule-get-coding-system (symbol-name group)))))
-               (if coding
-                   (setq str (gnus-decode-coding-string str (car coding))))
+               (when coding
+                 (setq str (mm-decode-coding-string str (car coding))))
                (set group str)))
            (forward-line 1))))
       (gnus-message 5 "Reading descriptions file...done")
                (set group str)))
            (forward-line 1))))
       (gnus-message 5 "Reading descriptions file...done")