*** empty log message ***
[gnus] / lisp / gnus-start.el
index 64c0272..974936e 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-start.el --- startup functions for Gnus
 ;;; gnus-start.el --- startup functions for Gnus
-;; Copyright (C) 1996,97 Free Software Foundation, Inc.
+;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
@@ -32,6 +32,7 @@
 (require 'gnus-range)
 (require 'gnus-util)
 (require 'message)
 (require 'gnus-range)
 (require 'gnus-util)
 (require 'message)
+(eval-when-compile (require 'cl))
 
 (defcustom gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc")
   "Your `.newsrc' file.
 
 (defcustom gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc")
   "Your `.newsrc' file.
   :type 'file)
 
 (defcustom gnus-init-file (nnheader-concat gnus-home-directory ".gnus")
   :type 'file)
 
 (defcustom gnus-init-file (nnheader-concat gnus-home-directory ".gnus")
-  "Your Gnus elisp startup file.
-If a file with the .el or .elc suffixes exist, it will be read
-instead."
+  "Your Gnus Emacs-Lisp startup file name.
+If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
   :group 'gnus-start
   :type 'file)
 
 (defcustom gnus-site-init-file
   :group 'gnus-start
   :type 'file)
 
 (defcustom gnus-site-init-file
-  (ignore-errors
-    (concat (file-name-directory
-            (directory-file-name installation-directory))
-           "site-lisp/gnus-init"))
-  "The site-wide Gnus elisp startup file.
-If a file with the .el or .elc suffixes exist, it will be read
-instead."
+  (condition-case nil
+      (concat (file-name-directory
+              (directory-file-name installation-directory))
+             "site-lisp/gnus-init")
+    (error nil))
+  "*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
   :group 'gnus-start
-  :type 'file)
+  :type '(choice file (const nil)))
 
 (defcustom gnus-default-subscribed-newsgroups nil
 
 (defcustom gnus-default-subscribed-newsgroups nil
-  "This variable lists what newsgroups should be subscribed the first time Gnus is used.
-It should be a list of strings.
-If it is `t', Gnus will not do anything special the first time it is
+  "List of newsgroups to subscribe, when a user runs Gnus the first time.
+The value should be a list of strings.
+If it is t, Gnus will not do anything special the first time it is
 started; it'll just use the normal newsgroups subscription methods."
   :group 'gnus-start
 started; it'll just use the normal newsgroups subscription methods."
   :group 'gnus-start
-  :type '(repeat string))
+  :type '(choice (repeat string) (const :tag "Nothing special" t)))
 
 (defcustom gnus-use-dribble-file t
   "*Non-nil means that Gnus will use a dribble file to store user updates.
 
 (defcustom gnus-use-dribble-file t
   "*Non-nil means that Gnus will use a dribble file to store user updates.
@@ -79,19 +79,19 @@ saved will be used."
   :group 'gnus-dribble-file
   :type '(choice directory (const nil)))
 
   :group 'gnus-dribble-file
   :type '(choice directory (const nil)))
 
-(defcustom gnus-check-new-newsgroups t
-  "*Non-nil means that Gnus will run gnus-find-new-newsgroups at startup.
+(defcustom gnus-check-new-newsgroups 'ask-server
+  "*Non-nil means that Gnus will run `gnus-find-new-newsgroups' at startup.
 This normally finds new newsgroups by comparing the active groups the
 servers have already reported with those Gnus already knows, either alive
 or killed.
 
 This normally finds new newsgroups by comparing the active groups the
 servers have already reported with those Gnus already knows, either alive
 or killed.
 
-When any of the following are true, gnus-find-new-newsgroups will instead
+When any of the following are true, `gnus-find-new-newsgroups' will instead
 ask the servers (primary, secondary, and archive servers) to list new
 groups since the last time it checked:
   1. This variable is `ask-server'.
   2. This variable is a list of select methods (see below).
   3. `gnus-read-active-file' is nil or `some'.
 ask the servers (primary, secondary, and archive servers) to list new
 groups since the last time it checked:
   1. This variable is `ask-server'.
   2. This variable is a list of select methods (see below).
   3. `gnus-read-active-file' is nil or `some'.
-  4. A prefix argument is given to gnus-find-new-newsgroups interactively.
+  4. A prefix argument is given to `gnus-find-new-newsgroups' interactively.
 
 Thus, if this variable is `ask-server' or a list of select methods or
 `gnus-read-active-file' is nil or `some', then the killed list is no
 
 Thus, if this variable is `ask-server' or a list of select methods or
 `gnus-read-active-file' is nil or `some', then the killed list is no
@@ -123,7 +123,7 @@ check for bogus newsgroups with \\<gnus-group-mode-map>\\[gnus-group-check-bogus
   :group 'gnus-start-server
   :type 'boolean)
 
   :group 'gnus-start-server
   :type 'boolean)
 
-(defcustom gnus-read-active-file t
+(defcustom gnus-read-active-file 'some
   "*Non-nil means that Gnus will read the entire active file at startup.
 If this variable is nil, Gnus will only know about the groups in your
 `.newsrc' file.
   "*Non-nil means that Gnus will read the entire active file at startup.
 If this variable is nil, Gnus will only know about the groups in your
 `.newsrc' file.
@@ -194,7 +194,8 @@ might take a while.  By setting this variable to nil, you'll save time,
 but you won't be told how many unread articles there are in the
 groups."
   :group 'gnus-group-levels
 but you won't be told how many unread articles there are in the
 groups."
   :group 'gnus-group-levels
-  :type 'integer)
+  :type '(choice integer
+                (const :tag "none" nil)))
 
 (defcustom gnus-save-newsrc-file t
   "*Non-nil means that Gnus will save the `.newsrc' file.
 
 (defcustom gnus-save-newsrc-file t
   "*Non-nil means that Gnus will save the `.newsrc' file.
@@ -228,7 +229,7 @@ not match this regexp will be removed before saving the list."
                         "[][\"#'()]"   ; bogus characters
                         )
                       "\\|"))
                         "[][\"#'()]"   ; bogus characters
                         )
                       "\\|"))
-  "A regexp to match uninteresting newsgroups in the active file.
+  "*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,
 thus making them effectively non-existent."
 Any lines in the active file matching this regular expression are
 removed from the newsgroup list before anything else is done to it,
 thus making them effectively non-existent."
@@ -288,7 +289,7 @@ hierarchy in its entirety."
   :type 'boolean)
 
 (defcustom gnus-auto-subscribed-groups
   :type 'boolean)
 
 (defcustom gnus-auto-subscribed-groups
-  "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
+  "nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
   "*All new groups that match this regexp will be subscribed automatically.
 Note that this variable only deals with new groups.  It has no effect
 whatsoever on old groups.
   "*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.
@@ -337,11 +338,22 @@ This hook is called after Gnus is connected to the NNTP server."
   :group 'gnus-start
   :type 'hook)
 
   :group 'gnus-start
   :type 'hook)
 
+(defcustom gnus-before-startup-hook nil
+  "A hook called at before startup.
+This hook is called as the first thing when Gnus is started."
+  :group 'gnus-start
+  :type 'hook)
+
 (defcustom gnus-started-hook nil
   "A hook called as the last thing after startup."
   :group 'gnus-start
   :type 'hook)
 
 (defcustom gnus-started-hook nil
   "A hook called as the last thing after startup."
   :group 'gnus-start
   :type 'hook)
 
+(defcustom gnus-setup-news-hook nil
+  "A hook after reading the .newsrc file, but before generating the buffer."
+  :group 'gnus-start
+  :type 'hook)
+
 (defcustom gnus-get-new-news-hook nil
   "A hook run just before Gnus checks for new news."
   :group 'gnus-group-new
 (defcustom gnus-get-new-news-hook nil
   "A hook run just before Gnus checks for new news."
   :group 'gnus-group-new
@@ -350,7 +362,7 @@ This hook is called after Gnus is connected to the NNTP server."
 (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."
   :group 'gnus-group-new
   :type 'hook)
 
   :group 'gnus-group-new
   :type 'hook)
 
@@ -373,6 +385,9 @@ Can be used to turn version control on or off."
 
 ;;; Internal variables
 
 
 ;;; Internal variables
 
+(defvar gnus-always-read-dribble-file nil
+  "Uncoditionally read the dribble file.")
+
 (defvar gnus-newsrc-file-version nil)
 (defvar gnus-override-subscribe-method nil)
 (defvar gnus-dribble-buffer nil)
 (defvar gnus-newsrc-file-version nil)
 (defvar gnus-override-subscribe-method nil)
 (defvar gnus-dribble-buffer nil)
@@ -434,7 +449,8 @@ Can be used to turn version control on or off."
              (push prefix prefixes)
              (message "Descend hierarchy %s? ([y]nsq): "
                       (substring prefix 1 (1- (length prefix))))
              (push prefix prefixes)
              (message "Descend hierarchy %s? ([y]nsq): "
                       (substring prefix 1 (1- (length prefix))))
-             (while (not (memq (setq ans (read-char)) '(?y ?\n ?\r ?n ?s ?q)))
+             (while (not (memq (setq ans (read-char-exclusive))
+                               '(?y ?\n ?\r ?n ?s ?q)))
                (ding)
                (message "Descend hierarchy %s? ([y]nsq): "
                         (substring prefix 1 (1- (length prefix)))))
                (ding)
                (message "Descend hierarchy %s? ([y]nsq): "
                         (substring prefix 1 (1- (length prefix)))))
@@ -462,7 +478,8 @@ Can be used to turn version control on or off."
                       (setq groups (cdr groups))))
                    (t nil)))
          (message "Subscribe %s? ([n]yq)" (car groups))
                       (setq groups (cdr groups))))
                    (t nil)))
          (message "Subscribe %s? ([n]yq)" (car groups))
-         (while (not (memq (setq ans (read-char)) '(?y ?\n ?\r ?q ?n)))
+         (while (not (memq (setq ans (read-char-exclusive))
+                           '(?y ?\n ?\r ?q ?n)))
            (ding)
            (message "Subscribe %s? ([n]yq)" (car groups)))
          (setq group (car groups))
            (ding)
            (message "Subscribe %s? ([n]yq)" (car groups)))
          (setq group (car groups))
@@ -591,7 +608,8 @@ the first newsgroup."
        gnus-newsgroup-data nil
        gnus-newsgroup-unreads nil
        nnoo-state-alist nil
        gnus-newsgroup-data nil
        gnus-newsgroup-unreads nil
        nnoo-state-alist nil
-       gnus-current-select-method nil)
+       gnus-current-select-method nil
+       gnus-ephemeral-servers nil)
   (gnus-shutdown 'gnus)
   ;; Kill the startup file.
   (and gnus-current-startup-file
   (gnus-shutdown 'gnus)
   ;; Kill the startup file.
   (and gnus-current-startup-file
@@ -629,10 +647,7 @@ 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")
 
 prompt the user for the name of an NNTP server to use."
   (interactive "P")
 
-  (if (and (get-buffer gnus-group-buffer)
-          (save-excursion
-            (set-buffer gnus-group-buffer)
-            (eq major-mode 'gnus-group-mode)))
+  (if (gnus-alive-p)
       (progn
        (switch-to-buffer gnus-group-buffer)
        (gnus-group-get-new-news
       (progn
        (switch-to-buffer gnus-group-buffer)
        (gnus-group-get-new-news
@@ -642,14 +657,19 @@ prompt the user for the name of an NNTP server to use."
 
     (gnus-splash)
     (gnus-clear-system)
 
     (gnus-splash)
     (gnus-clear-system)
+    (gnus-run-hooks 'gnus-before-startup-hook)
     (nnheader-init-server-buffer)
     (nnheader-init-server-buffer)
-    (gnus-read-init-file)
     (setq gnus-slave slave)
     (setq gnus-slave slave)
+    (gnus-read-init-file)
 
 
-    (when (and (string-match "XEmacs" (emacs-version))
-              gnus-simple-splash)
+    (when gnus-simple-splash
       (setq gnus-simple-splash nil)
       (setq gnus-simple-splash nil)
-      (gnus-xmas-splash))
+      (cond
+       (gnus-xemacs
+       (gnus-xmas-splash))
+       ((and (eq window-system 'x)
+            (= (frame-height) (1+ (window-height))))
+       (gnus-x-splash))))
 
     (let ((level (and (numberp arg) (> arg 0) arg))
          did-connect)
 
     (let ((level (and (numberp arg) (> arg 0) arg))
          did-connect)
@@ -661,7 +681,7 @@ prompt the user for the name of an NNTP server to use."
        (if (and (not dont-connect)
                 (not did-connect))
            (gnus-group-quit)
        (if (and (not dont-connect)
                 (not did-connect))
            (gnus-group-quit)
-         (run-hooks 'gnus-startup-hook)
+         (gnus-run-hooks 'gnus-startup-hook)
          ;; NNTP server is successfully open.
 
          ;; Find the current startup file name.
          ;; NNTP server is successfully open.
 
          ;; Find the current startup file name.
@@ -679,19 +699,30 @@ prompt the user for the name of an NNTP server to use."
 
          ;; Do the actual startup.
          (gnus-setup-news nil level dont-connect)
 
          ;; Do the actual startup.
          (gnus-setup-news nil level dont-connect)
+         (gnus-run-hooks 'gnus-setup-news-hook)
+         (gnus-start-draft-setup)
          ;; Generate the group buffer.
          (gnus-group-list-groups level)
          (gnus-group-first-unread-group)
          (gnus-configure-windows 'group)
          (gnus-group-set-mode-line)
          ;; Generate the group buffer.
          (gnus-group-list-groups level)
          (gnus-group-first-unread-group)
          (gnus-configure-windows 'group)
          (gnus-group-set-mode-line)
-         (run-hooks 'gnus-started-hook))))))
+         (gnus-run-hooks 'gnus-started-hook))))))
+
+(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)
+    (let ((gnus-level-default-subscribed 1))
+      (gnus-subscribe-group "nndraft:drafts" nil '(nndraft "")))
+    (gnus-group-set-parameter
+     "nndraft:drafts" 'gnus-dummy '((gnus-draft-mode)))))
 
 ;;;###autoload
 (defun gnus-unload ()
   "Unload all Gnus features."
   (interactive)
   (unless (boundp 'load-history)
 
 ;;;###autoload
 (defun gnus-unload ()
   "Unload all Gnus features."
   (interactive)
   (unless (boundp 'load-history)
-    (error "Sorry, `gnus-unload' is not implemented in this Emacs version."))
+    (error "Sorry, `gnus-unload' is not implemented in this Emacs version"))
   (let ((history load-history)
        feature)
     (while history
   (let ((history load-history)
        feature)
     (while history
@@ -728,6 +759,9 @@ prompt the user for the name of an NNTP server to use."
       (insert string "\n")
       (set-window-point (get-buffer-window (current-buffer)) (point-max))
       (bury-buffer gnus-dribble-buffer)
       (insert string "\n")
       (set-window-point (get-buffer-window (current-buffer)) (point-max))
       (bury-buffer gnus-dribble-buffer)
+      (save-excursion
+       (set-buffer gnus-group-buffer)
+       (gnus-group-set-mode-line))
       (set-buffer obuf))))
 
 (defun gnus-dribble-touch ()
       (set-buffer obuf))))
 
 (defun gnus-dribble-touch ()
@@ -766,8 +800,9 @@ prompt the user for the name of an NNTP server to use."
                     (setq modes (file-modes gnus-current-startup-file)))
            (set-file-modes dribble-file modes))
          ;; Possibly eval the file later.
                     (setq modes (file-modes gnus-current-startup-file)))
            (set-file-modes dribble-file modes))
          ;; Possibly eval the file later.
-         (when (gnus-y-or-n-p
-                "Gnus auto-save file exists.  Do you want to read it? ")
+         (when (or gnus-always-read-dribble-file
+                   (gnus-y-or-n-p
+                    "Gnus auto-save file exists.  Do you want to read it? "))
            (setq gnus-dribble-eval-file t)))))))
 
 (defun gnus-dribble-eval-file ()
            (setq gnus-dribble-eval-file t)))))))
 
 (defun gnus-dribble-eval-file ()
@@ -823,8 +858,10 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
       ;; Read the newsrc file and create `gnus-newsrc-hashtb'.
       (gnus-read-newsrc-file rawfile))
 
       ;; Read the newsrc file and create `gnus-newsrc-hashtb'.
       (gnus-read-newsrc-file rawfile))
 
-    (when (and (not (assoc "archive" gnus-server-alist))
-              (gnus-archive-server-wanted-p))
+    ;; 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))
 
       (push (cons "archive" gnus-message-archive-method)
            gnus-server-alist))
 
@@ -840,7 +877,7 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
     ;; done in `gnus-get-unread-articles'.
     (and gnus-read-active-file
         (not level)
     ;; done in `gnus-get-unread-articles'.
     (and gnus-read-active-file
         (not level)
-        (gnus-read-active-file))
+        (gnus-read-active-file nil dont-connect))
 
     (unless gnus-active-hashtb
       (setq gnus-active-hashtb (gnus-make-hashtable 4096)))
 
     (unless gnus-active-hashtb
       (setq gnus-active-hashtb (gnus-make-hashtable 4096)))
@@ -872,7 +909,8 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
     ;; Find new newsgroups and treat them.
     (when (and init gnus-check-new-newsgroups (not level)
               (gnus-check-server gnus-select-method)
     ;; Find new newsgroups and treat them.
     (when (and init gnus-check-new-newsgroups (not level)
               (gnus-check-server gnus-select-method)
-              (not gnus-slave))
+              (not gnus-slave)
+              gnus-plugged)
       (gnus-find-new-newsgroups))
 
     ;; We might read in new NoCeM messages here.
       (gnus-find-new-newsgroups))
 
     ;; We might read in new NoCeM messages here.
@@ -897,8 +935,8 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
   "Search for new newsgroups and add them.
 Each new newsgroup will be treated with `gnus-subscribe-newsgroup-method.'
 The `-n' option line from .newsrc is respected.
   "Search for new newsgroups and add them.
 Each new newsgroup will be treated with `gnus-subscribe-newsgroup-method.'
 The `-n' option line from .newsrc is respected.
-If ARG (the prefix), use the `ask-server' method to query
-the server for new groups."
+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)
   (interactive "P")
   (let ((check (if (or (and arg (not (listp gnus-check-new-newsgroups)))
                       (null gnus-read-active-file)
@@ -991,6 +1029,8 @@ the server for new groups."
         (new-date (current-time-string))
         group new-newsgroups got-new method hashtb
         gnus-override-subscribe-method)
         (new-date (current-time-string))
         group new-newsgroups got-new method hashtb
         gnus-override-subscribe-method)
+    (unless gnus-killed-hashtb
+      (gnus-make-hashtable-from-killed))
     ;; 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)))
@@ -1036,10 +1076,10 @@ the server for new groups."
         hashtb))
       (when new-newsgroups
        (gnus-subscribe-hierarchical-interactive new-newsgroups)))
         hashtb))
       (when new-newsgroups
        (gnus-subscribe-hierarchical-interactive new-newsgroups)))
-    ;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
-    (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))
     (when got-new
       (setq gnus-newsrc-last-checked-date new-date))
     got-new))
@@ -1052,7 +1092,8 @@ the server for new groups."
       nil
     (gnus-message 6 "First time user; subscribing you to default groups")
     (unless (gnus-read-active-file-p)
       nil
     (gnus-message 6 "First time user; subscribing you to default groups")
     (unless (gnus-read-active-file-p)
-      (gnus-read-active-file))
+      (let ((gnus-read-active-file t))
+       (gnus-read-active-file)))
     (setq gnus-newsrc-last-checked-date (current-time-string))
     (let ((groups gnus-default-subscribed-newsgroups)
          group)
     (setq gnus-newsrc-last-checked-date (current-time-string))
     (let ((groups gnus-default-subscribed-newsgroups)
          group)
@@ -1120,7 +1161,7 @@ the server for new groups."
     (if (and (not oldlevel)
             (consp entry))
        (setq oldlevel (gnus-info-level (nth 2 entry)))
     (if (and (not oldlevel)
             (consp entry))
        (setq oldlevel (gnus-info-level (nth 2 entry)))
-      (setq oldlevel (or oldlevel 9)))
+      (setq oldlevel (or oldlevel gnus-level-killed)))
     (when (stringp previous)
       (setq previous (gnus-gethash previous gnus-newsrc-hashtb)))
 
     (when (stringp previous)
       (setq previous (gnus-gethash previous gnus-newsrc-hashtb)))
 
@@ -1211,7 +1252,8 @@ the server for new groups."
           (format
            "(gnus-group-set-info '%S)" info)))))
       (when gnus-group-change-level-function
           (format
            "(gnus-group-set-info '%S)" info)))))
       (when gnus-group-change-level-function
-       (funcall gnus-group-change-level-function group level oldlevel)))))
+       (funcall gnus-group-change-level-function
+                group level oldlevel previous)))))
 
 (defun gnus-kill-newsgroup (newsgroup)
   "Obsolete function.  Kills a newsgroup."
 
 (defun gnus-kill-newsgroup (newsgroup)
   "Obsolete function.  Kills a newsgroup."
@@ -1265,7 +1307,7 @@ newsgroup."
              (set (car dead-lists)
                   (delete group (symbol-value (car dead-lists))))))
          (setq dead-lists (cdr dead-lists))))
              (set (car dead-lists)
                   (delete group (symbol-value (car dead-lists))))))
          (setq dead-lists (cdr dead-lists))))
-      (run-hooks 'gnus-check-bogus-groups-hook)
+      (gnus-run-hooks 'gnus-check-bogus-groups-hook)
       (gnus-message 5 "Checking bogus newsgroups...done"))))
 
 (defun gnus-check-duplicate-killed-groups ()
       (gnus-message 5 "Checking bogus newsgroups...done"))))
 
 (defun gnus-check-duplicate-killed-groups ()
@@ -1313,12 +1355,13 @@ newsgroup."
         ;; command may have responded with the `(0 . 0)'.  We
         ;; ignore this if we already have an active entry
         ;; for the group.
         ;; command may have responded with the `(0 . 0)'.  We
         ;; ignore this if we already have an active entry
         ;; for the group.
-        (unless (and (zerop (car active))
-                     (zerop (cdr active))
-                     (gnus-active group))
-          (gnus-set-active group active))
-        ;; Return the new active info.
-        active)))
+        (if (and (zerop (car active))
+                 (zerop (cdr active))
+                 (gnus-active group))
+            (gnus-active group)
+          (gnus-set-active group active)
+          ;; Return the new active info.
+          active))))
 
 (defun gnus-get-unread-articles-in-group (info active &optional update)
   (when active
 
 (defun gnus-get-unread-articles-in-group (info active &optional update)
   (when active
@@ -1561,11 +1604,12 @@ newsgroup."
   (gnus-dribble-touch))
 
 ;; Get the active file(s) from the backend(s).
   (gnus-dribble-touch))
 
 ;; Get the active file(s) from the backend(s).
-(defun gnus-read-active-file (&optional force)
+(defun gnus-read-active-file (&optional force not-native)
   (gnus-group-set-mode-line)
   (let ((methods
         (append
   (gnus-group-set-mode-line)
   (let ((methods
         (append
-         (if (gnus-check-server gnus-select-method)
+         (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
              ;; The native server is available.
              (cons gnus-select-method gnus-secondary-select-methods)
            ;; The native server is down, so we just do the
@@ -1617,18 +1661,20 @@ newsgroup."
                     1.2 "Cannot read partial active file from %s server."
                     (car method)))
                   ((eq list-type 'active)
                     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))
+                   (gnus-active-to-gnus-format
+                    method gnus-active-hashtb nil t))
                   (t
                   (t
-                   (gnus-groups-to-gnus-format method gnus-active-hashtb))))))
+                   (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)
             ((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."
+                   (gnus-error 1 "Cannot read active file from %s server"
                                (car method)))
                (gnus-message 5 mesg)
                                (car method)))
                (gnus-message 5 mesg)
-               (gnus-active-to-gnus-format method gnus-active-hashtb)
+               (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))))))
                ;; We mark this active file as read.
                (push method gnus-have-read-active-file)
                (gnus-message 5 "%sdone" mesg))))))
@@ -1643,7 +1689,8 @@ newsgroup."
                gnus-ignored-newsgroups))
 
 ;; Read an active file and place the results in `gnus-active-hashtb'.
                gnus-ignored-newsgroups))
 
 ;; Read an active file and place the results in `gnus-active-hashtb'.
-(defun gnus-active-to-gnus-format (&optional method hashtb ignore-errors)
+(defun gnus-active-to-gnus-format (&optional method hashtb ignore-errors
+                                            real-active)
   (unless method
     (setq method gnus-select-method))
   (let ((cur (current-buffer))
   (unless method
     (setq method gnus-select-method))
   (let ((cur (current-buffer))
@@ -1672,6 +1719,10 @@ newsgroup."
     (while (re-search-backward "[][';?()#]" nil t)
       (insert ?\\))
 
     (while (re-search-backward "[][';?()#]" nil t)
       (insert ?\\))
 
+    ;; Let the Gnus agent save the active file.
+    (when (and gnus-agent real-active)
+      (gnus-agent-save-active method))
+
     ;; If these are groups from a foreign select method, we insert the
     ;; group prefix in front of the group names.
     (when (not (gnus-server-equal
     ;; If these are groups from a foreign select method, we insert the
     ;; group prefix in front of the group names.
     (when (not (gnus-server-equal
@@ -1720,7 +1771,7 @@ newsgroup."
        (widen)
        (forward-line 1)))))
 
        (widen)
        (forward-line 1)))))
 
-(defun gnus-groups-to-gnus-format (method &optional hashtb)
+(defun gnus-groups-to-gnus-format (method &optional hashtb real-active)
   ;; Parse a "groups" active file.
   (let ((cur (current-buffer))
        (hashtb (or hashtb
   ;; Parse a "groups" active file.
   (let ((cur (current-buffer))
        (hashtb (or hashtb
@@ -1735,6 +1786,10 @@ newsgroup."
                           (gnus-server-get-method nil gnus-select-method)))
                     (gnus-group-prefixed-name "" method))))
 
                           (gnus-server-get-method nil gnus-select-method)))
                     (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.
     (goto-char (point-min))
     ;; We split this into to separate loops, one with the prefix
     ;; and one without to speed the reading up somewhat.
@@ -2152,11 +2207,12 @@ If FORCE is non-nil, the .newsrc file is read."
              (push (cons (concat
                           "^" (buffer-substring
                                (1+ (match-beginning 0))
              (push (cons (concat
                           "^" (buffer-substring
                                (1+ (match-beginning 0))
-                               (match-end 0)))
+                               (match-end 0))
+                          "\\($\\|\\.\\)")
                          'ignore)
                    out)
            ;; There was no bang, so this is a "yes" spec.
                          'ignore)
                    out)
            ;; There was no bang, so this is a "yes" spec.
-           (push (cons (concat "^" (match-string 0))
+           (push (cons (concat "^" (match-string 0) "\\($\\|\\.\\)")
                        'subscribe)
                  out))))
 
                        'subscribe)
                  out))))
 
@@ -2177,7 +2233,7 @@ If FORCE is non-nil, the .newsrc file is read."
                            (set-buffer gnus-dribble-buffer)
                            (buffer-size)))))
          (gnus-message 4 "(No changes need to be saved)")
                            (set-buffer gnus-dribble-buffer)
                            (buffer-size)))))
          (gnus-message 4 "(No changes need to be saved)")
-       (run-hooks 'gnus-save-newsrc-hook)
+       (gnus-run-hooks 'gnus-save-newsrc-hook)
        (if gnus-slave
            (gnus-slave-save-newsrc)
          ;; Save .newsrc.
        (if gnus-slave
            (gnus-slave-save-newsrc)
          ;; Save .newsrc.
@@ -2197,7 +2253,7 @@ If FORCE is non-nil, the .newsrc file is read."
          (erase-buffer)
          (gnus-message 5 "Saving %s.eld..." gnus-current-startup-file)
          (gnus-gnus-to-quick-newsrc-format)
          (erase-buffer)
          (gnus-message 5 "Saving %s.eld..." gnus-current-startup-file)
          (gnus-gnus-to-quick-newsrc-format)
-         (run-hooks 'gnus-save-quick-newsrc-hook)
+         (gnus-run-hooks 'gnus-save-quick-newsrc-hook)
          (save-buffer)
          (kill-buffer (current-buffer))
          (gnus-message
          (save-buffer)
          (kill-buffer (current-buffer))
          (gnus-message
@@ -2207,12 +2263,13 @@ If FORCE is non-nil, the .newsrc file is read."
 
 (defun gnus-gnus-to-quick-newsrc-format ()
   "Insert Gnus variables such as gnus-newsrc-alist in lisp format."
 
 (defun gnus-gnus-to-quick-newsrc-format ()
   "Insert Gnus variables such as gnus-newsrc-alist in lisp format."
-  (let ((print-quoted t))
+  (let ((print-quoted t)
+       (print-escape-newlines t))
     (insert ";; -*- emacs-lisp -*-\n")
     (insert ";; Gnus startup file.\n")
     (insert ";; -*- emacs-lisp -*-\n")
     (insert ";; Gnus startup file.\n")
-    (insert
-     ";; Never delete this file - touch .newsrc instead to force Gnus\n")
-    (insert ";; to read .newsrc.\n")
+    (insert "\
+;; Never delete this file -- if you want to force Gnus to read the
+;; .newsrc file (if you have one), touch .newsrc instead.\n")
     (insert "(setq gnus-newsrc-file-version "
            (prin1-to-string gnus-version) ")\n")
     (let* ((gnus-killed-list
     (insert "(setq gnus-newsrc-file-version "
            (prin1-to-string gnus-version) ")\n")
     (let* ((gnus-killed-list
@@ -2241,7 +2298,7 @@ If FORCE is non-nil, the .newsrc file is read."
   (let ((list gnus-killed-list)
        olist)
     (while list
   (let ((list gnus-killed-list)
        olist)
     (while list
-      (when (string-match gnus-save-killed-list)
+      (when (string-match gnus-save-killed-list (car list))
        (push (car list) olist))
       (pop list))
     (nreverse olist)))
        (push (car list) olist))
       (pop list))
     (nreverse olist)))
@@ -2298,7 +2355,7 @@ If FORCE is non-nil, the .newsrc file is read."
       (if gnus-modtime-botch
          (delete-file gnus-startup-file)
        (clear-visited-file-modtime))
       (if gnus-modtime-botch
          (delete-file gnus-startup-file)
        (clear-visited-file-modtime))
-      (run-hooks 'gnus-save-standard-newsrc-hook)
+      (gnus-run-hooks 'gnus-save-standard-newsrc-hook)
       (save-buffer)
       (kill-buffer (current-buffer)))))
 
       (save-buffer)
       (kill-buffer (current-buffer)))))
 
@@ -2433,8 +2490,16 @@ If FORCE is non-nil, the .newsrc file is read."
            (skip-chars-forward " \t")
            ;; ...  which leads to this line being effectively ignored.
            (when (symbolp group)
            (skip-chars-forward " \t")
            ;; ...  which leads to this line being effectively ignored.
            (when (symbolp group)
-             (set group (buffer-substring
-                         (point) (progn (end-of-line) (point)))))
+             (let ((str (buffer-substring
+                         (point) (progn (end-of-line) (point))))
+                   (coding
+                    (and (boundp 'enable-multibyte-characters)
+                         enable-multibyte-characters
+                         (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))))
+               (set group str)))
            (forward-line 1))))
       (gnus-message 5 "Reading descriptions file...done")
       t))))
            (forward-line 1))))
       (gnus-message 5 "Reading descriptions file...done")
       t))))